using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UXAssist.Common;
using UXAssist.UI;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("InterstellarLogisticsOpt")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Staggers interstellar logistics scheduling to reduce CPU load / 相位分散星际物流调度,降低 CPU 开销")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+85595c55e003b209486f944cf622b06320ca049a")]
[assembly: AssemblyProduct("InterstellarLogisticsOpt")]
[assembly: AssemblyTitle("InterstellarLogisticsOpt")]
[assembly: AssemblyVersion("1.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace InterstellarLogisticsOpt
{
[HarmonyPatch(typeof(StationComponent), "DetermineDispatch")]
internal static class DispatchOptimization
{
internal static readonly bool SupportedGame = typeof(StationComponent).Module.ModuleVersionId == new Guid("ece4a40e-5e73-43f4-a9f8-4e74970b5942");
internal static volatile bool Enabled;
internal static string Failure;
private static bool NeedsLock(StationComponent peer, int index, int priority)
{
if (priority == 0 || priority > 4)
{
return false;
}
ref StationPriorityLock reference = ref peer.priorityLocks[index];
if (reference.priorityIndex != 0 && reference.priorityIndex < priority)
{
return false;
}
int num;
switch (priority)
{
default:
num = 60;
break;
case 2:
case 3:
num = 30;
break;
case 1:
num = 10;
break;
}
int num2 = num;
if (reference.priorityIndex == priority)
{
return reference.lockTick != num2;
}
return true;
}
[HarmonyTranspiler]
[HarmonyAfter(new string[] { "org.fyyy.logisticsprofiler" })]
internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
//IL_0238: Unknown result type (might be due to invalid IL or missing references)
//IL_0242: Expected O, but got Unknown
//IL_024f: Unknown result type (might be due to invalid IL or missing references)
//IL_0259: Expected O, but got Unknown
//IL_027e: Unknown result type (might be due to invalid IL or missing references)
//IL_0288: Expected O, but got Unknown
//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
//IL_02bb: Expected O, but got Unknown
//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
//IL_03f7: Expected O, but got Unknown
//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0405: Expected O, but got Unknown
//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
//IL_02ea: Expected O, but got Unknown
//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0300: Expected O, but got Unknown
//IL_031c: Unknown result type (might be due to invalid IL or missing references)
//IL_0326: Expected O, but got Unknown
//IL_0340: Unknown result type (might be due to invalid IL or missing references)
//IL_034a: Expected O, but got Unknown
List<CodeInstruction> code = instructions.ToList();
FieldInfo fieldInfo = AccessTools.Field(typeof(StationComponent), "storage");
List<int> list = new List<int>();
for (int i = 0; i + 8 < code.Count; i++)
{
if (CodeInstructionExtensions.IsLdarg(code[i], (int?)5) && CodeInstructionExtensions.IsLdloc(code[i + 1], (LocalBuilder)null) && (CodeInstructionExtensions.LoadsField(code[i + 2], AccessTools.Field(typeof(SupplyDemandPair), "supplyId"), false) || CodeInstructionExtensions.LoadsField(code[i + 2], AccessTools.Field(typeof(SupplyDemandPair), "demandId"), false)) && code[i + 3].opcode == OpCodes.Ldelem_Ref && CodeInstructionExtensions.IsStloc(code[i + 4], (LocalBuilder)null) && CodeInstructionExtensions.IsLdloc(code[i + 5], (LocalBuilder)null) && code[i + 6].opcode == OpCodes.Brfalse && CodeInstructionExtensions.IsLdloc(code[i + 7], (LocalBuilder)null) && CodeInstructionExtensions.LoadsField(code[i + 8], fieldInfo, false))
{
list.Add(i);
}
}
if (!SupportedGame || list.Count != 2 || list.Any((int num) => code[num + 7].blocks.Count != 0))
{
Failure = "Unsupported DetermineDispatch body; dispatch optimization was not applied.";
return code;
}
Failure = null;
LocalBuilder localBuilder = generator.DeclareLocal(typeof(bool));
foreach (int item in list.AsEnumerable().Reverse())
{
int index = item + 7;
Label label = generator.DefineLabel();
bool flag = CodeInstructionExtensions.LoadsField(code[item + 2], AccessTools.Field(typeof(SupplyDemandPair), "demandId"), false);
List<CodeInstruction> list2 = new List<CodeInstruction>
{
new CodeInstruction(OpCodes.Ldloc, (object)localBuilder),
new CodeInstruction(OpCodes.Brfalse, (object)label),
new CodeInstruction(code[index].opcode, code[index].operand),
new CodeInstruction(code[item + 1].opcode, code[item + 1].operand),
new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(SupplyDemandPair), flag ? "demandIndex" : "supplyIndex")),
new CodeInstruction(OpCodes.Ldarg_S, (object)(byte)4),
new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DispatchOptimization), "NeedsLock", (Type[])null, (Type[])null)),
new CodeInstruction(OpCodes.Brfalse, code[item + 6].operand)
};
list2[0].labels.AddRange(code[index].labels);
code[index].labels.Clear();
code[index].labels.Add(label);
code.InsertRange(index, list2);
}
code.InsertRange(0, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
{
new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(DispatchOptimization), "Enabled")),
new CodeInstruction(OpCodes.Stloc, (object)localBuilder)
});
return code;
}
}
[HarmonyPatch(typeof(GalacticTransport), "GameTick")]
internal static class DispatchScheduler
{
internal static volatile int Factor = 1;
[HarmonyPrefix]
private static bool Prefix(GalacticTransport __instance, long time)
{
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Invalid comparison between Unknown and I4
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Invalid comparison between Unknown and I4
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Invalid comparison between Unknown and I4
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Invalid comparison between Unknown and I4
int factor = Factor;
if (!DispatchOptimization.Enabled || factor <= 1 || !DispatchOptimization.SupportedGame || DispatchOptimization.Failure != null)
{
return true;
}
GameData gameData = __instance.gameData;
GameHistoryData history = gameData.history;
float logisticShipSailSpeedModified = history.logisticShipSailSpeedModified;
float num = (history.logisticShipWarpDrive ? history.logisticShipWarpSpeedModified : logisticShipSailSpeedModified);
StationComponent[] stationPool = __instance.stationPool;
for (int i = 1; i <= 6; i++)
{
int num2 = i % 6;
int num3;
switch (i)
{
default:
num3 = 60;
break;
case 2:
case 3:
num3 = 30;
break;
case 1:
num3 = 10;
break;
}
int num4 = num3 * factor;
for (int j = (int)(time % num4) + 1; j < __instance.stationCursor; j += num4)
{
StationComponent val = stationPool[j];
if (val == null || val.id <= 0 || val.gid != j)
{
continue;
}
ERemoteRoutePriority routePriority = val.routePriority;
bool num5;
if (num2 != 0)
{
if ((int)routePriority != 2)
{
if (num2 > 4)
{
continue;
}
if ((int)routePriority != 3)
{
num5 = (int)routePriority == 4;
goto IL_00e3;
}
}
goto IL_00e5;
}
num5 = (int)routePriority == 1;
goto IL_00e3;
IL_00e5:
val.DetermineDispatch(logisticShipSailSpeedModified, num, history.logisticShipCarries, num2, stationPool, gameData.statistics.production.factoryStatPool, gameData.factories, gameData.galaxy, gameData.statistics.traffic);
continue;
IL_00e3:
if (!num5)
{
continue;
}
goto IL_00e5;
}
}
return false;
}
}
[BepInPlugin("org.fyyy.interstellarlogisticsopt", "InterstellarLogisticsOpt", "1.2.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class InterstellarLogisticsOptPlugin : BaseUnityPlugin
{
public static ConfigEntry<bool> ModEnabled;
public static ConfigEntry<int> AmortizeFactor;
private Harmony _harmony;
private void Awake()
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Expected O, but got Unknown
ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Optimize interstellar dispatch / 优化星际物流派船");
AmortizeFactor = ((BaseUnityPlugin)this).Config.Bind<int>("General", "AmortizeFactor", 1, new ConfigDescription("All-route scheduling multiplier. 1 = vanilla cadence. At N > 1, stagger stations across ticks and run dispatch checks at 1/N frequency. Trades priority fidelity and responsiveness for lower CPU cost; may limit throughput. / 全航线调度间隔系数。1 为原版节奏;N > 1 时按塔错开调度,检查频率降为 1/N。以部分优先级准确性和响应速度换取更低 CPU 开销,可能限制吞吐。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), Array.Empty<object>()));
ModEnabled.SettingChanged += UpdateSettings;
AmortizeFactor.SettingChanged += UpdateSettings;
UpdateSettings(null, EventArgs.Empty);
_harmony = new Harmony("org.fyyy.interstellarlogisticsopt");
_harmony.PatchAll(typeof(DispatchOptimization));
_harmony.PatchAll(typeof(DispatchScheduler));
if (DispatchOptimization.Failure != null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)DispatchOptimization.Failure);
}
I18N.Add("InterstellarLogisticsOpt", "InterstellarLogisticsOpt", "星际物流优化");
I18N.Add("Optimize interstellar dispatch", "Optimize interstellar dispatch", "优化星际物流派船计算");
I18N.Add("Dispatch interval multiplier", "Dispatch interval multiplier", "全航线调度间隔系数");
I18N.Apply();
MyConfigWindow.OnUICreated = (Action<MyConfigWindow, RectTransform>)Delegate.Combine(MyConfigWindow.OnUICreated, new Action<MyConfigWindow, RectTransform>(CreateUI));
}
private static void UpdateSettings(object sender, EventArgs e)
{
DispatchOptimization.Enabled = ModEnabled.Value;
DispatchScheduler.Factor = AmortizeFactor.Value;
}
private void OnDestroy()
{
MyConfigWindow.OnUICreated = (Action<MyConfigWindow, RectTransform>)Delegate.Remove(MyConfigWindow.OnUICreated, new Action<MyConfigWindow, RectTransform>(CreateUI));
if (ModEnabled != null)
{
ModEnabled.SettingChanged -= UpdateSettings;
}
if (AmortizeFactor != null)
{
AmortizeFactor.SettingChanged -= UpdateSettings;
}
DispatchOptimization.Enabled = false;
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
private static void CreateUI(MyConfigWindow wnd, RectTransform trans)
{
((MyWindowWithTabs)wnd).AddSplitter(trans, 10f);
((MyWindowWithTabs)wnd).AddTabGroup(trans, "InterstellarLogisticsOpt", "tab-group-interstellarlogisticsopt");
RectTransform val = ((MyWindowWithTabs)wnd).AddTab(trans, "InterstellarLogisticsOpt");
((MyWindow)wnd).AddCheckBox(0f, 10f, val, ModEnabled, "Optimize interstellar dispatch", 15);
Text val2 = ((MyWindow)wnd).AddText2(0f, 51f, val, "Dispatch interval multiplier", 14, "label");
((MyWindow)wnd).AddSlider<int>(val2.preferredWidth + 10f, 46f, val, AmortizeFactor, (ValueMapper<int>)(object)new RangeValueMapper<int>(1, 30), "0", 200f).WithSmallerHandle(10f, 0f);
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "org.fyyy.interstellarlogisticsopt";
public const string PLUGIN_NAME = "InterstellarLogisticsOpt";
public const string PLUGIN_VERSION = "1.2.0";
}
}