1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2026-03-27 20:27:12 +08:00

Compare commits

...

30 Commits

Author SHA1 Message Date
09cdaf3a12 balance tweaks 2025-10-30 16:03:11 +08:00
8d5bb140e1 fix crashes 2025-10-30 00:12:47 +08:00
c99c59a117 work in progress 2025-10-29 22:30:10 +08:00
61811f9a8c crash fix 2025-10-29 21:51:52 +08:00
cf3117e0da minor opt 2025-10-29 21:38:53 +08:00
dfd34601cf update for new game update 2025-10-29 20:54:41 +08:00
6934607fca WIP for logistic_hub 2025-10-29 20:45:21 +08:00
be9de43492 fix issue 2025-10-29 20:22:23 +08:00
2dbf017a5e update LogisticMiner to be compatible with latest game update 2025-10-29 15:27:53 +08:00
3c7744047c update Game dll 2025-10-29 15:27:23 +08:00
a9959a2f07 try to fix a strange issue 2025-10-29 15:27:13 +08:00
77f5803a24 UniverseGenTweaks v1.2.11 2025-10-21 00:36:32 +08:00
e9bbcf5e2c bug fix 2025-10-20 22:45:29 +08:00
a183485286 UXAssist: some fixes 2025-10-04 17:23:41 +08:00
5a6cfb18c9 UXAssist: Drag build Power Towers fix 2025-10-03 16:16:02 +08:00
49226001be UXAssist v1.4.2 2025-09-30 13:02:39 +08:00
7c1e88f86d UXAssist v1.4.1 2025-09-30 00:15:26 +08:00
16429936a9 UXAssist v1.4.0 and CheatEnabler v2.4.0 2025-09-29 23:46:44 +08:00
d711dd25ef remove cpu affinity settings, as they are officially supported 2025-09-29 23:34:17 +08:00
e909b6d9d2 rename GameLogicProc back to make things compatible with old dependants 2025-09-29 23:34:17 +08:00
2a4008deac fixed rest issues 2025-09-29 23:34:17 +08:00
6b423225fe partial fix belt signal 2025-09-29 23:34:17 +08:00
9d9a12c1af more fixes to make sure nothing working wrong on game 2025-09-29 23:34:17 +08:00
1d11ba90bd we make them compile first 2025-09-29 23:34:17 +08:00
a5dc7c5825 Starmap view star name display: add star index 2025-09-29 17:02:10 +08:00
73ebcf1aa3 more works 2025-09-28 17:36:19 +08:00
dc092d7f6f Planet Vein Utilization embedded 2025-09-28 00:42:16 +08:00
d9f87ca4e9 Logistics Panel Info fix again again 2025-09-24 15:06:09 +08:00
a3c60c32ca Logistics Panel Info fix again 2025-09-24 12:19:50 +08:00
96a9e8a570 Logistics Panel Info fix 2025-09-24 02:51:41 +08:00
53 changed files with 2296 additions and 1881 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -3,6 +3,9 @@
## Changlog
* 2.4.0
* Support game version 0.10.33
* `Generate illegal dyson shell`: This function is open to all users now, enabling certain config entry is not needed any more.
* 2.3.32
* `Complete Dyson Sphere Shells instantly`: Fix a crash.
* 2.3.31
@@ -162,6 +165,9 @@
## 更新日志
* 2.4.0
* 支持游戏版本 0.10.33
* `生成仙术戴森壳`:此功能现在对所有用户开放,不再需要启用特定的配置项。
* 2.3.32
* `立即完成戴森壳建造`:修复了一个崩溃问题
* 2.3.31

View File

@@ -5,7 +5,7 @@
<TargetFramework>net472</TargetFramework>
<BepInExPluginGuid>org.soardev.cheatenabler</BepInExPluginGuid>
<Description>DSP MOD - CheatEnabler</Description>
<Version>2.3.32</Version>
<Version>2.4.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<PackageId>CheatEnabler</PackageId>
@@ -16,15 +16,14 @@
<ItemGroup>
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
<PackageReference Include="DysonSphereProgram.GameLibs" Version="0.10.32.*-r.*" />
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
<PackageReference Include="UnityEngine.Modules" Version="2022.3.53" IncludeAssets="compile" />
<!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="0.10.32.*-r.*" /> -->
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
</ItemGroup>
<!--
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath>
@@ -33,13 +32,12 @@
<HintPath>..\AssemblyFromGame\UnityEngine.UI.dll</HintPath>
</Reference>
</ItemGroup>
-->
<ItemGroup>
<ProjectReference Include="..\UXAssist\UXAssist.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip&#xA;powershell Compress-Archive -Force -DestinationPath 'package/$(ProjectName)-$(Version).zip' -Path '$(TargetPath)', package/icon.png, package/manifest.json, README.md, CHANGELOG.md" />
</Target>
</Project>

View File

@@ -5,7 +5,6 @@ using System.Threading;
using System.Threading.Tasks;
using BepInEx.Configuration;
using HarmonyLib;
using Unity.Jobs;
using UnityEngine;
using UXAssist.Common;

View File

@@ -4,7 +4,7 @@ using System.Reflection.Emit;
using BepInEx.Configuration;
using HarmonyLib;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace CheatEnabler.Patches;
@@ -134,12 +134,12 @@ public class DysonSpherePatch : PatchImpl<DysonSpherePatch>
{
UpdateSailLifeTime();
UpdateSailsCacheForThisGame();
GameLogic.OnGameBegin += GameMain_Begin_Postfix;
GameLogicProc.OnGameBegin += GameMain_Begin_Postfix;
}
protected override void OnDisable()
{
GameLogic.OnGameBegin -= GameMain_Begin_Postfix;
GameLogicProc.OnGameBegin -= GameMain_Begin_Postfix;
}
private static void UpdateSailLifeTime()
@@ -296,7 +296,7 @@ public class DysonSpherePatch : PatchImpl<DysonSpherePatch>
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DysonSwarm), "GameTick")]
[HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.GameTick))]
public static void DysonSwarm_GameTick_Prefix(DysonSwarm __instance, long time)
{
var index = __instance.starData.index;

View File

@@ -8,7 +8,7 @@ using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace CheatEnabler.Patches;
@@ -94,14 +94,14 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
ControlPanelRemoteLogistics.Enable(ControlPanelRemoteLogisticsEnabled.Value);
Enable(true);
CargoTrafficPatch.Enable(true);
GameLogic.OnGameBegin += GameMain_Begin_Postfix_For_ImmBuild;
GameLogic.OnDataLoaded += OnDataLoaded;
GameLogicProc.OnGameBegin += GameMain_Begin_Postfix_For_ImmBuild;
GameLogicProc.OnDataLoaded += OnDataLoaded;
}
public static void Uninit()
{
GameLogic.OnDataLoaded -= OnDataLoaded;
GameLogic.OnGameBegin -= GameMain_Begin_Postfix_For_ImmBuild;
GameLogicProc.OnDataLoaded -= OnDataLoaded;
GameLogicProc.OnGameBegin -= GameMain_Begin_Postfix_For_ImmBuild;
CargoTrafficPatch.Enable(false);
Enable(false);
ImmediateBuild.Enable(false);
@@ -496,7 +496,7 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
}
[HarmonyPostfix]
[HarmonyPatch(typeof(StorageComponent), "GetItemCount", typeof(int))]
[HarmonyPatch(typeof(StorageComponent), nameof(StorageComponent.GetItemCount), typeof(int))]
public static void GetItemCountPatch(StorageComponent __instance, int itemId, ref int __result)
{
if (__result > 99) return;
@@ -629,12 +629,12 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
protected override void OnEnable()
{
InitSignalBelts();
GameLogic.OnGameBegin += GameMain_Begin_Postfix;
GameLogicProc.OnGameBegin += GameMain_Begin_Postfix;
}
protected override void OnDisable()
{
GameLogic.OnGameBegin -= GameMain_Begin_Postfix;
GameLogicProc.OnGameBegin -= GameMain_Begin_Postfix;
_initialized = false;
_signalBelts = null;
_signalBeltsCapacity = 0;
@@ -995,7 +995,7 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
var data = GameMain.data;
var factories = data?.factories;
if (factories == null) return;
PerformanceMonitor.BeginSample(ECpuWorkEntry.Belt);
DeepProfiler.BeginSample(DPEntry.Belt);
for (var index = data.factoryCount - 1; index >= 0; index--)
{
var factory = factories[index];
@@ -1123,23 +1123,16 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
}
}
PerformanceMonitor.EndSample(ECpuWorkEntry.Belt);
DeepProfiler.EndSample(DPEntry.Belt);
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(GameData), "GameTick")]
public static IEnumerable<CodeInstruction> GameData_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions)
[HarmonyPostfix]
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.OnFactoryFrameBegin))]
public static void GameLogic_OnFactoryFrameBegin_Postfix()
{
var matcher = new CodeMatcher(instructions);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(PerformanceMonitor), nameof(PerformanceMonitor.EndSample)))
).Advance(1).Insert(
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(BeltSignalGenerator), nameof(ProcessBeltSignals)))
);
return matcher.InstructionEnumeration();
ProcessBeltSignals();
}
/* BEGIN: Item sources calculation */
private static readonly Dictionary<int, ItemSource> ItemSources = [];
private static bool _itemSourcesInitialized;

View File

@@ -64,19 +64,19 @@ public static class GamePatch
}
[HarmonyPrefix]
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyBeforeGameSave")]
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnAssemblerRecipePick")]
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnGameBegin")]
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnMechaForgeTaskComplete")]
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnUnlockTech")]
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnUseConsole")]
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyBeforeGameSave))]
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnAssemblerRecipePick))]
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnGameBegin))]
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnMechaForgeTaskComplete))]
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnUnlockTech))]
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnUseConsole))]
private static bool DisableAbnormalLogic()
{
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(AbnormalityLogic), "InitDeterminators")]
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.InitDeterminators))]
private static void DisableAbnormalDeterminators(AbnormalityLogic __instance)
{
_savedDeterminators = __instance.determinators;
@@ -282,7 +282,7 @@ public static class GamePatch
}
}
history.VarifyTechQueue();
history.VerifyTechQueue();
if (history.currentTech != history.techQueue[0])
{
history.currentTech = history.techQueue[0];

View File

@@ -31,10 +31,10 @@ public static class ResourcePatch
private class InfiniteResource : PatchImpl<InfiniteResource>
{
static private readonly float InfiniteResourceRate = 0f;
[HarmonyTranspiler]
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool))]
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool), typeof(int), typeof(int), typeof(int))]
[HarmonyPatch(typeof(ItemProto), nameof(ItemProto.GetPropValue))]
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic._miner_parallel))]
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.GameTick))]
[HarmonyPatch(typeof(UIChartAstroResource), nameof(UIChartAstroResource.CalculateMaxAmount))]
[HarmonyPatch(typeof(UIChartVeinGroup), nameof(UIChartVeinGroup.CalculateMaxAmount))]
@@ -42,18 +42,29 @@ public static class ResourcePatch
[HarmonyPatch(typeof(UIControlPanelVeinCollectorPanel), nameof(UIControlPanelVeinCollectorPanel._OnUpdate))]
[HarmonyPatch(typeof(UIMinerWindow), nameof(UIMinerWindow._OnUpdate))]
[HarmonyPatch(typeof(UIMiningUpgradeLabel), nameof(UIMiningUpgradeLabel.Update))]
[HarmonyPatch(typeof(UIStationStorage), nameof(UIStationStorage.RefreshValues))]
[HarmonyPatch(typeof(UIVeinCollectorPanel), nameof(UIVeinCollectorPanel._OnUpdate))]
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningCostRate)))
new CodeMatch(ci => (ci.opcode == OpCodes.Ldfld || ci.opcode == OpCodes.Ldflda) && ci.OperandIs(AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningCostRate))))
).Repeat(codeMatcher =>
codeMatcher.RemoveInstruction().InsertAndAdvance(
new CodeInstruction(OpCodes.Pop),
new CodeInstruction(OpCodes.Ldc_R4, 0f)
)
{
if (codeMatcher.Instruction.opcode == OpCodes.Ldfld)
{
codeMatcher.RemoveInstruction().InsertAndAdvance(
new CodeInstruction(OpCodes.Pop),
new CodeInstruction(OpCodes.Ldc_R4, InfiniteResourceRate)
);
}
else
{
codeMatcher.RemoveInstruction().InsertAndAdvance(
new CodeInstruction(OpCodes.Pop),
new CodeInstruction(OpCodes.Ldsflda, AccessTools.Field(typeof(InfiniteResource), nameof(InfiniteResourceRate)))
);
}
}
);
return matcher.InstructionEnumeration();
}
@@ -61,29 +72,51 @@ public static class ResourcePatch
private class FastMining : PatchImpl<FastMining>
{
static private readonly float FastMiningSpeed = 2400f;
[HarmonyTranspiler]
[HarmonyPatch(typeof(FactorySystem), "GameTick", typeof(long), typeof(bool))]
[HarmonyPatch(typeof(FactorySystem), "GameTick", typeof(long), typeof(bool), typeof(int), typeof(int), typeof(int))]
[HarmonyPatch(typeof(ItemProto), "GetPropValue")]
[HarmonyPatch(typeof(PlanetTransport), "GameTick")]
[HarmonyPatch(typeof(UIMinerWindow), "_OnUpdate")]
[HarmonyPatch(typeof(UIMiningUpgradeLabel), "Update")]
[HarmonyPatch(typeof(UIPlanetDetail), "OnPlanetDataSet")]
[HarmonyPatch(typeof(UIPlanetDetail), "RefreshDynamicProperties")]
[HarmonyPatch(typeof(UIStarDetail), "OnStarDataSet")]
[HarmonyPatch(typeof(UIStarDetail), "RefreshDynamicProperties")]
[HarmonyPatch(typeof(UIStationStorage), "RefreshValues")]
[HarmonyPatch(typeof(UIVeinCollectorPanel), "_OnUpdate")]
[HarmonyPatch(typeof(AstroResourceStatPlan), nameof(AstroResourceStatPlan.AddPlanetResources))]
[HarmonyPatch(typeof(BuildingGizmo), nameof(BuildingGizmo.Update))]
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool))]
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic._miner_parallel))]
[HarmonyPatch(typeof(ItemProto), nameof(ItemProto.GetPropValue))]
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.GameTick))]
[HarmonyPatch(typeof(ProductionExtraInfoCalculator), nameof(ProductionExtraInfoCalculator.CalculateFactory))]
[HarmonyPatch(typeof(UIChartAstroResource), nameof(UIChartAstroResource.CalculateMaxAmount))]
[HarmonyPatch(typeof(UIChartVeinGroup), nameof(UIChartVeinGroup.CalculateMaxAmount))]
[HarmonyPatch(typeof(UIControlPanelStationStorage), nameof(UIControlPanelStationStorage.RefreshValues))]
[HarmonyPatch(typeof(UIControlPanelVeinCollectorPanel), nameof(UIControlPanelVeinCollectorPanel._OnUpdate))]
[HarmonyPatch(typeof(UIMinerWindow), nameof(UIMinerWindow._OnUpdate))]
[HarmonyPatch(typeof(UIMiningUpgradeLabel), nameof(UIMiningUpgradeLabel.Update))]
[HarmonyPatch(typeof(UIPlanetDetail), nameof(UIPlanetDetail.OnPlanetDataSet))]
[HarmonyPatch(typeof(UIPlanetDetail), nameof(UIPlanetDetail.RefreshDynamicProperties))]
[HarmonyPatch(typeof(UIReferenceSpeedTip), nameof(UIReferenceSpeedTip.AddEntryDataWithFactory))]
[HarmonyPatch(typeof(UIStarDetail), nameof(UIStarDetail.OnStarDataSet))]
[HarmonyPatch(typeof(UIStarDetail), nameof(UIStarDetail.RefreshDynamicProperties))]
[HarmonyPatch(typeof(UIStationStorage), nameof(UIStationStorage.RefreshValues))]
[HarmonyPatch(typeof(UIVeinCollectorPanel), nameof(UIVeinCollectorPanel._OnUpdate))]
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningSpeedScale)))
new CodeMatch(ci => (ci.opcode == OpCodes.Ldfld || ci.opcode == OpCodes.Ldflda) && ci.OperandIs(AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningSpeedScale))))
).Repeat(codeMatcher =>
codeMatcher.RemoveInstruction().InsertAndAdvance(
new CodeInstruction(OpCodes.Pop),
new CodeInstruction(OpCodes.Ldc_R4, 2400f)
)
{
if (codeMatcher.Instruction.opcode == OpCodes.Ldfld)
{
codeMatcher.RemoveInstruction().InsertAndAdvance(
new CodeInstruction(OpCodes.Pop),
new CodeInstruction(OpCodes.Ldc_R4, FastMiningSpeed)
);
}
else
{
codeMatcher.RemoveInstruction().InsertAndAdvance(
new CodeInstruction(OpCodes.Pop),
new CodeInstruction(OpCodes.Ldsflda, AccessTools.Field(typeof(FastMining), nameof(FastMiningSpeed)))
);
}
}
);
return matcher.InstructionEnumeration();
}

View File

@@ -49,7 +49,7 @@
* Eject anyway
* Unlock Dyson Sphere max orbit radius
* Complete Dyson Sphere Shells instantly
* Buttons for creating illegal Dyson Sphere Shells, you must enable `IllegalDysonShellFunctionsEnabled` of `DysonSphere` section in config to see them.
* Buttons for creating illegal Dyson Sphere Shells, you must enable `IllegalDysonShellFunctionsEnabled` of `DysonSphere` section in config to see the last 2 buttons.
* Generate an illegal dyson shell
* Keep max production shells and remove others
* Duplicate shells from that with highest production
@@ -123,7 +123,7 @@
* 全球弹射
* 解锁戴森球最大轨道半径
* 立即完成戴森壳建造
* 用于制作仙术戴森壳的按钮,你必须在设置文件里开启`DysonSphere`分类的`IllegalDysonShellFunctionsEnabled`才能看到它们
* 用于制作仙术戴森壳的按钮,你必须在设置文件里开启`DysonSphere`分类的`IllegalDysonShellFunctionsEnabled`才能看到后面两个按钮
* 生成单层仙术戴森壳
* 保留发电量最高的戴森壳并移除其他戴森壳
* 从发电量最高的壳复制戴森壳

View File

@@ -1,10 +1,10 @@
{
"name": "CheatEnabler",
"version_number": "2.3.32",
"version_number": "2.4.0",
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/CheatEnabler",
"description": "Add various cheat functions while disabling abnormal determinants / 添加一些作弊功能,同时屏蔽异常检测",
"dependencies": [
"xiaoye97-BepInEx-5.4.17",
"soarqin-UXAssist-1.2.0"
"soarqin-UXAssist-1.4.0"
]
}

View File

@@ -4,7 +4,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UXAssist", "UXAssist\UXAssi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CheatEnabler", "CheatEnabler\CheatEnabler.csproj", "{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogisticMiner", "LogisticMiner\LogisticMiner.csproj", "{7149D717-C913-4153-9425-38CB9D087F83}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogisticHub", "LogisticHub\LogisticHub.csproj", "{7149D717-C913-4153-9425-38CB9D087F83}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HideTips", "HideTips\HideTips.csproj", "{4EABD71D-477F-448B-801B-48F8745A3FA7}"
EndProject

View File

@@ -152,7 +152,7 @@ public class HideTips : BaseUnityPlugin
class HideMenuDemo
{
[HarmonyPriority(Priority.First), HarmonyPrefix]
[HarmonyPatch(typeof(DSPGame), "StartDemoGame", typeof(int))]
[HarmonyPatch(typeof(DSPGame), nameof(DSPGame.StartDemoGame), typeof(int))]
private static bool DSPGame_StartDemoGame_Prefix()
{
if (DSPGame.Game != null)
@@ -188,7 +188,7 @@ class HideMenuDemo
}
[HarmonyPriority(Priority.First), HarmonyPrefix]
[HarmonyPatch(typeof(VFPreload), "IsMenuDemoLoaded")]
[HarmonyPatch(typeof(VFPreload), nameof(VFPreload.IsMenuDemoLoaded))]
private static bool VFPreload_IsMenuDemoLoaded_Prefix(ref bool __result)
{
__result = true;
@@ -196,18 +196,18 @@ class HideMenuDemo
}
[HarmonyPriority(Priority.First), HarmonyPrefix]
[HarmonyPatch(typeof(DSPGame), "LateUpdate")]
[HarmonyPatch(typeof(GameMain), "LateUpdate")]
[HarmonyPatch(typeof(GameMain), "FixedUpdate")]
[HarmonyPatch(typeof(GameMain), "Update")]
[HarmonyPatch(typeof(GameCamera), "LateUpdate")]
[HarmonyPatch(typeof(DSPGame), nameof(DSPGame.LateUpdate))]
[HarmonyPatch(typeof(GameMain), nameof(GameMain.LateUpdate))]
[HarmonyPatch(typeof(GameMain), nameof(GameMain.FixedUpdate))]
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Update))]
[HarmonyPatch(typeof(GameCamera), nameof(GameCamera.LateUpdate))]
private static bool DSPGame_LateUpdate_Prefix()
{
return !DSPGame.IsMenuDemo;
}
[HarmonyPriority(Priority.First), HarmonyPrefix]
[HarmonyPatch(typeof(GameMain), "Begin")]
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
private static bool GameMain_Begin_Prefix()
{
if (!DSPGame.IsMenuDemo) return true;

View File

@@ -0,0 +1,57 @@
using System;
using System.Reflection;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UXAssist.Common;
namespace LogisticHub;
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
public class LogisticHub : BaseUnityPlugin
{
public new static readonly BepInEx.Logging.ManualLogSource Logger =
BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME);
private Type[] _modules;
private void Awake()
{
Module.Miner.Enabled = Config.Bind("Miner", "Enabled", true, "enable/disable this plugin");
Module.Miner.OreEnergyConsume = Config.Bind("Miner", "EnergyConsumptionForOre", 2000000L,
"Energy consumption for each ore vein group(in W)");
Module.Miner.OreMiningMultiplier = Config.Bind("Miner", "OreMiningMultiplier", 3,
new ConfigDescription("Mining multiplier for ore veins, multiplies to the number of veins in the group", new AcceptableValueRange<int>(1, 100)));
Module.Miner.OreMiningScale = Config.Bind("Miner", "OreMiningScale", 100,
"""
0 for Auto(which means having researched advanced mining machine makes mining scale 300, otherwise 100).
Mining scale(in percents) for slots below half of slot limits, and the scale reduces to 100% smoothly till reach full.
Please note that the power consumption increases by the square of the scale which is the same as Advanced Mining Machine.
""");
Module.Miner.OilEnergyConsume = Config.Bind("Miner", "EnergyConsumptionForOil", 1800000L,
"Energy consumption for each oil seep(in W)");
Module.Miner.WaterEnergyConsume = Config.Bind("Miner", "EnergyConsumptionForWater", 2000000L,
"Energy consumption for water slot(in W)");
Module.Miner.WaterSpeed = Config.Bind("Miner", "WaterMiningSpeed", 10,
"Water mining speed (count per second)");
Module.Miner.FuelIlsSlot = Config.Bind("Miner", "ILSFuelSlot", 4,
new ConfigDescription("Fuel slot for ILS, set 0 to disable.", new AcceptableValueRange<int>(0, 5)));
Module.Miner.FuelPlsSlot = Config.Bind("Miner", "PLSFuelSlot", 4,
new ConfigDescription("Fuel slot for PLS, set 0 to disable.", new AcceptableValueRange<int>(0, 4)));
_modules = Util.GetTypesFiltered(Assembly.GetExecutingAssembly(),
t => string.Equals(t.Namespace, "LogisticHub.Module", StringComparison.Ordinal));
_modules?.Do(type => type.GetMethod("Init")?.Invoke(null, null));
Harmony.CreateAndPatchAll(typeof(LogisticHub));
}
private void Start()
{
_modules?.Do(type => type.GetMethod("Start")?.Invoke(null, null));
}
private void OnDestroy()
{
_modules?.Do(type => type.GetMethod("Uninit")?.Invoke(null, null));
}
}

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<BepInExPluginGuid>org.soardev.logistichub</BepInExPluginGuid>
<Description>DSP MOD - LogisticHub</Description>
<Version>0.1.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
<PackageId>LogisticHub</PackageId>
<RootNamespace>LogisticHub</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
<PackageReference Include="UnityEngine.Modules" Version="2022.3.53" IncludeAssets="compile" />
<!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="0.10.32.*-r.*" /> -->
</ItemGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>..\AssemblyFromGame\UnityEngine.UI.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UXAssist\UXAssist.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,33 @@
using System.Linq;
namespace LogisticHub.Module;
using UXAssist.Common;
public static class AuxData
{
public static (long, bool)[] Fuels;
public static void Init()
{
GameLogic.OnDataLoaded += () =>
{
var maxId = LDB.items.dataArray.Select(data => data.ID).Prepend(0).Max();
Fuels = new (long, bool)[maxId + 1];
foreach (var data in LDB.items.dataArray)
Fuels[data.ID] = (data.HeatValue, data.Productive);
};
}
public static int AlignUpToPowerOf2(int n)
{
if (n < 16) return 16;
n--;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
return n + 1;
}
}

View File

345
LogisticHub/Module/Miner.cs Normal file
View File

@@ -0,0 +1,345 @@
using System;
using BepInEx.Configuration;
using HarmonyLib;
using UXAssist.Common;
using Random = UnityEngine.Random;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace LogisticHub.Module;
public class Miner : PatchImpl<Miner>
{
public static ConfigEntry<bool> Enabled;
public static ConfigEntry<long> OreEnergyConsume;
public static ConfigEntry<int> OreMiningScale;
public static ConfigEntry<int> OreMiningMultiplier;
public static ConfigEntry<long> OilEnergyConsume;
public static ConfigEntry<long> WaterEnergyConsume;
public static ConfigEntry<int> WaterSpeed;
public static ConfigEntry<int> FuelIlsSlot;
public static ConfigEntry<int> FuelPlsSlot;
private static long _frame;
private static float _miningCostRateByTech;
private static long _miningFrames;
private static long _miningSpeedScaleLong;
private static bool _advancedMiningMachineUnlocked;
private static int _miningMultiplier = 3;
private static int _miningScale = 100;
private static uint _miningCostBarrier;
private static uint _miningCostBarrierOil;
private static int[] _mineIndex;
private static uint _miningSeed = (uint)Random.Range(0, int.MaxValue);
private static readonly (int, int)[] VeinList =
[
(0, 1000),
(1, 1001),
(2, 1002),
(3, 1003),
(4, 1004),
(5, 1005),
(6, 1006),
(7, 1007),
(11, 1011),
(12, 1012),
(13, 1013),
(14, 1014),
(15, 1015),
(16, 1016)
];
public static void Init()
{
Enabled.SettingChanged += (_, _) => { Enable(Enabled.Value); };
Enable(Enabled.Value);
}
public static void Uninit()
{
Enable(false);
}
protected override void OnEnable()
{
GameLogicProc.OnGameBegin += OnGameBegin;
}
protected override void OnDisable()
{
GameLogicProc.OnGameBegin -= OnGameBegin;
}
private static void OnGameBegin()
{
_frame = 0L;
UpdateMiningCostRate();
UpdateSpeedScale();
CheckRecipes();
}
private static int SplitIncLevel(ref int n, ref int m, int p)
{
var level = m / n;
var left = m - level * n;
n -= p;
left -= n;
m -= left > 0 ? level * p + left : level * p;
return level;
}
private static void CheckRecipes()
{
_advancedMiningMachineUnlocked = GameMain.history.recipeUnlocked.Contains(119);
_miningMultiplier = OreMiningMultiplier.Value;
if (OreMiningScale.Value == 0)
{
_miningScale = _advancedMiningMachineUnlocked ? 300 : 100;
}
else
{
_miningScale = OreMiningScale.Value;
}
}
private static void UpdateMiningCostRate()
{
_miningCostRateByTech = GameMain.history.miningCostRate;
_miningCostBarrier = (uint)(int)Math.Ceiling(2147483646.0 * _miningCostRateByTech);
_miningCostBarrierOil = (uint)(int)Math.Ceiling(2147483646.0 * _miningCostRateByTech * 0.401116669f / Math.Max(DSPGame.GameDesc.resourceMultiplier, 0.416666657f));
}
private static void UpdateSpeedScale()
{
_miningSpeedScaleLong = (long)Math.Round(GameMain.history.miningSpeedScale * 100f);
_miningFrames = _miningSpeedScaleLong * 6000L;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameHistoryData), nameof(GameHistoryData.UnlockTechFunction))]
private static void OnUnlockTech(int func)
{
switch (func)
{
case 20:
UpdateMiningCostRate();
break;
case 21:
UpdateSpeedScale();
break;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.OnFactoryFrameBegin))]
private static void GameLogic_OnFactoryFrameBegin_Prefix()
{
var main = GameMain.instance;
if (main.isMenuDemo) return;
if (_miningSpeedScaleLong <= 0L) return;
if (main.timei % 60 != 0) return;
_frame += _miningFrames;
var frameCounter = _frame / 1200000L;
if (frameCounter <= 0) return;
_frame -= frameCounter * 1200000L;
DeepProfiler.BeginSample(DPEntry.Miner);
var data = GameMain.data;
if (_mineIndex == null || data.factoryCount > _mineIndex.Length)
Array.Resize(ref _mineIndex, data.factoryCount);
var factoryStatPool = GameMain.statistics.production.factoryStatPool;
for (var factoryIndex = data.factoryCount - 1; factoryIndex >= 0; factoryIndex--)
{
var factory = data.factories[factoryIndex];
var veins = VeinManager.GetVeins(factoryIndex);
if (veins == null) continue;
var stations = StationManager.GetStations(factoryIndex);
var planetTransport = factory.transport;
var productRegister = factoryStatPool[factoryIndex]?.productRegister;
var demands = stations.StorageIndices[1];
if (demands == null) continue;
foreach (var (itemIndex, itemId) in VeinList)
{
if (itemIndex >= demands.Length) continue;
var demandList = demands[itemIndex];
if (demandList == null) continue;
foreach (var storageIndex in demandList)
{
var station = planetTransport.stationPool[storageIndex / 100];
if (station == null)
continue;
ref var storage = ref station.storage[storageIndex % 100];
if (storage.count >= storage.max) continue;
int amount;
long energyConsume;
var miningScale = _miningScale;
if (miningScale > 100 && storage.count * 2 > storage.max)
{
miningScale = 100 + ((miningScale - 100) * (storage.max - storage.count) * 2 + storage.max - 1) / storage.max;
}
if (itemIndex > 0)
{
(amount, energyConsume) = Mine(factory, veins, itemId, miningScale, (int)frameCounter, _miningMultiplier, station.energy);
if (amount < 0) continue;
}
else
{
energyConsume = (WaterEnergyConsume.Value * frameCounter * miningScale * miningScale + 9999L) / 10000L;
if (station.energy < energyConsume) continue;
amount = WaterSpeed.Value * miningScale / 100;
}
if (amount <= 0) continue;
storage.count += amount;
if (productRegister != null)
productRegister[itemId] += amount;
station.energy -= energyConsume;
}
}
for (var i = planetTransport.stationCursor - 1; i > 0; i--)
{
var stationComponent = planetTransport.stationPool[i];
if (stationComponent == null || stationComponent.isCollector || stationComponent.isVeinCollector || stationComponent.energy * 2 >= stationComponent.energyMax) continue;
var index = (stationComponent.isStellar ? FuelIlsSlot.Value : FuelPlsSlot.Value) - 1;
var storage = stationComponent.storage;
if (index < 0 || index >= storage.Length)
continue;
var fuelCount = storage[index].count;
if (fuelCount == 0) continue;
var (heat, prod) = AuxData.Fuels[storage[index].itemId];
if (heat <= 0)
continue;
/* Sprayed fuels */
int pretendIncLevel;
if (prod && (pretendIncLevel = storage[index].inc / storage[index].count) > 0)
{
var count = (int)((stationComponent.energyMax - stationComponent.energy) * 1000L / Cargo.incTable[pretendIncLevel] / 7L);
if (count > fuelCount)
count = fuelCount;
var incLevel = SplitIncLevel(ref storage[index].count, ref storage[index].inc, count);
if (incLevel > 10)
incLevel = 10;
stationComponent.energy += heat * count * (1000L + Cargo.incTable[incLevel]) / 1000L;
}
else
{
var count = (int)((stationComponent.energyMax - stationComponent.energy) / heat);
if (count > fuelCount)
count = fuelCount;
SplitIncLevel(ref storage[index].count, ref storage[index].inc, count);
stationComponent.energy += heat * count;
}
}
}
DeepProfiler.EndSample(DPEntry.Miner);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameHistoryData), nameof(GameHistoryData.UnlockRecipe))]
private static void OnUnlockRecipe(int recipeId)
{
if (recipeId == 119)
{
CheckRecipes();
}
}
private static (int, long) Mine(PlanetFactory factory, ProductVeinData[] allVeins, int productId, int percent, int counter, int multiplier, long energyMax)
{
var veins = allVeins[productId - 1000];
if (veins == null)
return (-1, -1L);
var veinIndices = veins.VeinIndices;
uint barrier;
int limit;
int count;
long energy;
var length = veinIndices.Count - 1;
/* if is Oil */
if (productId == 1007)
{
energy = OilEnergyConsume.Value * length;
if (energy > energyMax)
return (-1, -1L);
var countf = 0f;
var veinsPool = factory.veinPool;
for (var i = length; i > 0; i--)
{
countf += veinsPool[veinIndices[i]].amount * 4 * VeinData.oilSpeedMultiplier;
}
count = (int)(countf * (counter * percent) / 100f);
if (count == 0)
return (-1, -1L);
barrier = _miningCostBarrierOil;
limit = 2500;
}
else
{
count = (length * multiplier * counter * percent + 99) / 100;
if (count == 0)
return (-1, -1L);
energy = (OreEnergyConsume.Value * veins.GroupCount * percent * percent + 9999L) / 10000L;
if (energy > energyMax)
return (-1, -1L);
barrier = _miningCostBarrier;
limit = 0;
}
var veinsData = factory.veinPool;
var total = 0;
var factoryIndex = factory.index;
var mineIndex = _mineIndex[factoryIndex];
for (; count > 0; count--)
{
mineIndex = mineIndex % length + 1;
var index = veinIndices[mineIndex];
ref var vd = ref veinsData[index];
int groupIndex;
if (vd.amount <= 0)
{
groupIndex = vd.groupIndex;
factory.veinGroups[groupIndex].count--;
factory.RemoveVeinWithComponents(index);
factory.RecalculateVeinGroup(groupIndex);
length = veinIndices.Count - 1;
if (length <= 0) break;
continue;
}
total++;
if (vd.amount <= limit) continue;
var consume = true;
if (barrier < 2147483646u)
{
_miningSeed = (uint)((int)((ulong)((_miningSeed % 2147483646u + 1) * 48271L) % 2147483647uL) - 1);
consume = _miningSeed < barrier;
}
if (!consume) continue;
vd.amount--;
groupIndex = vd.groupIndex;
factory.veinGroups[groupIndex].amount--;
if (vd.amount > 0) continue;
factory.veinGroups[groupIndex].count--;
factory.RemoveVeinWithComponents(index);
factory.RecalculateVeinGroup(groupIndex);
length = veinIndices.Count - 1;
if (length <= 0) break;
}
_mineIndex[factoryIndex] = mineIndex;
return (total, energy);
}
}

View File

@@ -0,0 +1,325 @@
using System;
using System.Collections.Generic;
using HarmonyLib;
using UXAssist.Common;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace LogisticHub.Module;
public class PlanetStations
{
public readonly List<int>[][] StorageIndices = [null, null];
public void AddStationStorage(bool demand, int id, int stationId, int storageIdx)
{
LogisticHub.Logger.LogDebug($"AddStationStorage: demand={demand}, id={id}, stationId={stationId}, storageIdx={storageIdx}");
var stations = StorageIndices[demand ? 1 : 0];
if (stations == null || id >= stations.Length)
{
Array.Resize(ref stations, AuxData.AlignUpToPowerOf2(id + 1));
StorageIndices[demand ? 1 : 0] = stations;
}
var list = stations[id];
if (list == null)
{
list = [];
stations[id] = list;
}
var value = stationId * 100 + storageIdx;
var index = list.BinarySearch(value);
if (index < 0)
list.Insert(~index, value);
}
public void RemoveStationStorage(bool demand, int id, int stationId, int storageIdx)
{
var stations = StorageIndices[demand ? 1 : 0];
if (stations == null || id >= stations.Length)
return;
var list = stations[id];
if (list == null)
return;
var value = stationId * 100 + storageIdx;
var index = list.BinarySearch(value);
if (index >= 0)
list.RemoveAt(index);
}
}
public class StationManager : PatchImpl<StationManager>
{
private static PlanetStations[] _stations;
public static void Init()
{
GameLogicProc.OnGameBegin += OnGameBegin;
Enable(true);
}
public static void Uninit()
{
GameLogicProc.OnGameBegin -= OnGameBegin;
Enable(false);
}
private static void OnGameBegin()
{
_stations = null;
var data = GameMain.data;
for (var index = data.factoryCount - 1; index >= 0; index--)
{
var factory = data.factories[index];
if (factory == null || factory.index != index) continue;
var planetIndex = factory.index;
var stations = StationsByPlanet(planetIndex);
var transport = factory.transport;
var pool = transport.stationPool;
for (var i = transport.stationCursor - 1; i > 0; i--)
{
var station = pool[i];
if (station == null || station.id != i || station.isCollector || station.isVeinCollector) continue;
UpdateStationInfo(stations, station);
}
}
}
private static int ItemIdToIndex(int itemId)
{
return itemId switch
{
>= 1000 and < 2000 => itemId - 1000,
>= 5000 and < 5050 => itemId - 5000 + 900,
>= 6000 and < 6050 => itemId - 6000 + 950,
_ => -1
};
}
public static int IndexToItemId(int index)
{
return index switch
{
< 900 => index + 1000,
< 950 => index - 900 + 5000,
< 1000 => index - 950 + 6000,
_ => -1
};
}
public static PlanetStations GetStations(int planetIndex)
{
return _stations != null && planetIndex < _stations.Length ? _stations[planetIndex] : null;
}
private static PlanetStations StationsByPlanet(int planetIndex)
{
if (_stations == null || _stations.Length <= planetIndex)
Array.Resize(ref _stations, AuxData.AlignUpToPowerOf2(planetIndex + 1));
var stations = _stations[planetIndex];
if (stations != null) return stations;
stations = new PlanetStations();
_stations[planetIndex] = stations;
return stations;
}
private static void DebugLog()
{
for (var idx = 0; idx < _stations.Length; idx++)
{
var stations = _stations[idx];
if (stations == null) continue;
LogisticHub.Logger.LogDebug($"Planet {idx}:");
for (var i = 0; i < 2; i++)
{
var storage = stations.StorageIndices[i];
if (storage == null) continue;
LogisticHub.Logger.LogDebug(i == 1 ? " Demand:" : " Supply:");
for (var j = 0; j < storage.Length; j++)
{
var list = storage[j];
if (list == null) continue;
var count = list.Count;
if (count <= 0) continue;
var itemId = IndexToItemId(j);
LogisticHub.Logger.LogDebug($" {itemId}: {string.Join(", ", list)}");
}
}
}
}
private static void UpdateStationInfo(PlanetStations stations, StationComponent station, int storageIdx = -1)
{
var storage = station.storage;
var stationId = station.id;
if (storageIdx >= 0)
{
if (storageIdx >= storage.Length) return;
var itemId = ItemIdToIndex(storage[storageIdx].itemId);
if (itemId <= 0) return;
var logic = storage[storageIdx].localLogic;
switch (logic)
{
case ELogisticStorage.Demand:
stations.AddStationStorage(true, itemId, stationId, storageIdx);
break;
case ELogisticStorage.Supply:
stations.AddStationStorage(false, itemId, stationId, storageIdx);
break;
case ELogisticStorage.None:
default:
break;
}
return;
}
for (var i = storage.Length - 1; i >= 0; i--)
{
var itemId = ItemIdToIndex(storage[i].itemId);
if (itemId <= 0) continue;
var logic = storage[i].localLogic;
switch (logic)
{
case ELogisticStorage.Demand:
stations.AddStationStorage(true, itemId, stationId, i);
break;
case ELogisticStorage.Supply:
stations.AddStationStorage(false, itemId, stationId, i);
break;
case ELogisticStorage.None:
default:
break;
}
}
}
private static void RemoveStationInfo(PlanetStations stations, StationComponent station, int storageIdx = -1)
{
var storage = station.storage;
var stationId = station.id;
if (storageIdx >= 0)
{
var itemId = ItemIdToIndex(storage[storageIdx].itemId);
if (itemId <= 0) return;
var logic = storage[storageIdx].localLogic;
switch (logic)
{
case ELogisticStorage.Demand:
stations.RemoveStationStorage(true, itemId, stationId, storageIdx);
break;
case ELogisticStorage.Supply:
stations.RemoveStationStorage(false, itemId, stationId, storageIdx);
break;
case ELogisticStorage.None:
default:
break;
}
return;
}
for (var i = storage.Length - 1; i >= 0; i--)
{
var itemId = ItemIdToIndex(storage[i].itemId);
if (itemId <= 0) continue;
var logic = storage[i].localLogic;
switch (logic)
{
case ELogisticStorage.Demand:
stations.RemoveStationStorage(true, itemId, stationId, i);
break;
case ELogisticStorage.Supply:
stations.RemoveStationStorage(false, itemId, stationId, i);
break;
case ELogisticStorage.None:
default:
break;
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.Init))]
private static void PlanetTransport_Init_Postfix(PlanetTransport __instance)
{
var factory = __instance.factory;
var planetIndex = factory.index;
if (_stations == null || _stations.Length <= planetIndex)
Array.Resize(ref _stations, AuxData.AlignUpToPowerOf2(planetIndex + 1));
var stations = new PlanetStations();
_stations[planetIndex] = stations;
var pool = __instance.stationPool;
for (var i = __instance.stationCursor - 1; i > 0; i--)
{
var station = pool[i];
if (station == null || station.id != i || station.isCollector || station.isVeinCollector) continue;
UpdateStationInfo(stations, station);
}
// DebugLog();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(BuildingParameters), nameof(BuildingParameters.ApplyPrebuildParametersToEntity))]
private static void BuildingParameters_ApplyPrebuildParametersToEntity_Postfix(int entityId, PlanetFactory factory)
{
if (entityId <= 0) return;
ref var entity = ref factory.entityPool[entityId];
var stationId = entity.stationId;
if (stationId <= 0) return;
var station = factory.transport.stationPool[stationId];
if (station == null || station.id != stationId || station.isCollector || station.isVeinCollector) return;
UpdateStationInfo(StationsByPlanet(factory.index), station);
// DebugLog();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.RemoveStationComponent))]
private static void PlanetTransport_RemoveStationComponent_Prefix(PlanetTransport __instance, int id)
{
if (id <= 0) return;
var station = __instance.stationPool[id];
if (station == null || station.id != id || station.isCollector || station.isVeinCollector) return;
RemoveStationInfo(StationsByPlanet(__instance.factory.index), station);
// DebugLog();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.SetStationStorage))]
private static void PlanetTransport_SetStationStorage_Prefix(PlanetTransport __instance, int stationId, int storageIdx, int itemId, ELogisticStorage localLogic, out bool __state)
{
var station = __instance.stationPool[stationId];
if (station == null || station.id != stationId || station.isCollector || station.isVeinCollector || storageIdx < 0 || storageIdx >= station.storage.Length)
{
__state = false;
return;
}
ref var storage = ref station.storage[storageIdx];
var oldItemId = storage.itemId;
var oldLocalLogic = storage.localLogic;
if (localLogic == oldLocalLogic && itemId == oldItemId)
{
__state = false;
return;
}
if (oldItemId > 0 && oldLocalLogic != ELogisticStorage.None)
RemoveStationInfo(StationsByPlanet(__instance.factory.index), station, storageIdx);
__state = localLogic != ELogisticStorage.None;
// if (!__state) DebugLog();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.SetStationStorage))]
private static void PlanetTransport_SetStationStorage_Postfix(PlanetTransport __instance, int stationId, int storageIdx, bool __state)
{
if (!__state) return;
var station = __instance.stationPool[stationId];
UpdateStationInfo(StationsByPlanet(__instance.factory.index), station, storageIdx);
// DebugLog();
}
}

View File

@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using HarmonyLib;
using UXAssist.Common;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace LogisticHub.Module;
public class ProductVeinData
{
public readonly List<int> VeinIndices = [];
public readonly HashSet<int> GroupIndices = [];
public int GroupCount = 0;
}
public class VeinManager : PatchImpl<VeinManager>
{
private static ProductVeinData[][] _veins;
public static void Init()
{
Enable(true);
GameLogicProc.OnGameBegin += OnGameBegin;
}
public static void Uninit()
{
GameLogicProc.OnGameBegin -= OnGameBegin;
Enable(false);
}
private static void OnGameBegin()
{
_veins = null;
var data = GameMain.data;
for (var index = data.factoryCount - 1; index >= 0; index--)
{
var factory = data.factories[index];
if (factory == null || factory.index != index) continue;
RecalcVeins(factory);
}
}
public static ProductVeinData[] GetVeins(int planetIndex)
{
if (_veins == null || _veins.Length <= planetIndex)
return null;
return _veins[planetIndex];
}
private static ProductVeinData[] GetOrCreateVeins(int planetIndex)
{
if (_veins == null || _veins.Length <= planetIndex)
Array.Resize(ref _veins, AuxData.AlignUpToPowerOf2(planetIndex + 1));
var veins = _veins[planetIndex];
if (veins != null) return veins;
veins = new ProductVeinData[20];
_veins[planetIndex] = veins;
return veins;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.Init))]
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.RecalculateVeinGroup))]
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.RecalculateAllVeinGroups))]
private static void PlanetFactory_RecalculateAllVeinGroups_Postfix(PlanetFactory __instance)
{
RecalcVeins(__instance);
}
private static void DebugLog()
{
foreach (var veins in _veins)
{
if (veins == null) continue;
for (var i = 0; i < veins.Length; i++)
{
var pvd = veins[i];
if (pvd == null) continue;
LogisticHub.Logger.LogInfo($"Product {i} VeinTypeCount={pvd.VeinIndices.Count} GroupCount={pvd.GroupCount}");
}
}
}
private static void RecalcVeins(PlanetFactory factory)
{
var planetIndex = factory.index;
var veins = GetOrCreateVeins(planetIndex);
var veinPool = factory.veinPool;
foreach (var pvd in veins)
{
if (pvd == null) continue;
pvd.VeinIndices.Clear();
pvd.GroupIndices.Clear();
pvd.GroupCount = 0;
}
for (var i = factory.veinCursor - 1; i > 0; i--)
{
if (veinPool[i].id != i || veinPool[i].amount <= 0 || veinPool[i].type == EVeinType.None) continue;
var productId = veinPool[i].productId - 1000;
if (productId is < 0 or >= 20) continue;
var pvd = veins[productId];
if (pvd == null)
{
pvd = new ProductVeinData();
veins[productId] = pvd;
}
pvd.VeinIndices.Add(i);
pvd.GroupIndices.Add(veinPool[i].groupIndex);
}
foreach (var pvd in veins)
{
if (pvd == null) continue;
pvd.GroupCount = pvd.GroupIndices.Count;
}
// DebugLog();
}
}

47
LogisticHub/README.md Normal file
View File

@@ -0,0 +1,47 @@
# LogisticHub
#### Cheat functions for Logistic Storages, make them mine resources on the planet and exchange items from certain buildings
#### 物流塔作弊功能,使其可以在星球上采矿并与特定建筑物交换物品
## Usage
* Miner(and fuel burning) functions
+ Inspired by [PlanetMiner](https://dsp.thunderstore.io/package/blacksnipebiu/PlanetMiner)([github](https://github.com/blacksnipebiu/PlanetMiner))
But it is heavily optimized to resolve performance, accuracy and other issues in PlanetMiner.
+ (Optimization to PlanetMiner) Only recalculate count of veins when vein chunks are changed (added/removed by foundations/Sandbox-Mode, or exhausted), so this removes Dictionary allocation on each planet for every frame.
+ (Optimization to PlanetMiner) More accurate frame counting by use float number.
+ (Optimization to PlanetMiner) Does not increase power consumptions on `Veins Utilization` upgrades.
+ (Optimization to PlanetMiner) Separate power consumptions for veins, oil seeps and water.
+ (Optimization to PlanetMiner) Power consumptions are counted by groups of veins and count of oil seeps, which is more sensible.
+ Can burn fuels in certain slot when energy below half of max.
- (Optimization to PlanetMiner) Sprayed fuels generates extra energy as normal.
+ (Optimization to PlanetMiner) All used parameters are configurable:
- LogisticHub has the same speed as normal Mining Machine for normal ores by default.
But you can set mining scale in configuration, which makes LogisticHub working like Advance Mining Machines:
power consumption increases by the square of the scale, and gradually decrease mining speed over half of the maximum count.
This applies to all of veins, oils and water.
Mining scale can be set to 0(by default), which means it is automatically set by tech unlocks, set to 300 when you reaches Advanced Mining Machine, otherwise 100.
- 100/s for water by default.
- Energy costs: 1MW/vein-group & 10MW/water-slot & 1.8MW/oil-seep(configurable)
- Fuels burning slot. Default: 4th for ILS and PLS. Set to 0 to disable it.
## 使用说明
* 采矿(和燃料燃烧)功能
+ 创意来自 [PlanetMiner](https://dsp.thunderstore.io/package/blacksnipebiu/PlanetMiner)([github](https://github.com/blacksnipebiu/PlanetMiner))
对性能重度优化并解决了PlanetMiner的精度等问题。
+ (对PlanetMiner的优化) 仅当矿堆发生变化(填埋/恢复/采完)时重新计算矿堆数据,解决每行星每计算帧要重建字典的性能问题。
+ (对PlanetMiner的优化) 用浮点数保证更精确的帧计算。
+ (对PlanetMiner的优化) 升级`矿物利用`不会提升能耗。
+ (对PlanetMiner的优化) 分开矿物,油井和水的采集能耗。
+ (对PlanetMiner的优化) 采集能耗以矿物组,油井为单位,相对更加合理。
+ 剩余电量少于一半时可以燃烧指定格子的燃料补充。
- (对PlanetMiner的优化) 喷涂了增产剂的燃料按照正常的计算方式提供更多的能量(除了原本就不增加能量输出的反物质燃料棒)。
+ (对PlanetMiner的优化) 所有参数都可以在设置文件内配置:
- 物流塔枢纽和普通矿机采矿速度一样(等同于同时采集所有对应矿物)。
你可以设置采矿倍率改变物流塔枢纽采矿速度,和高级采矿机相同地,能耗和倍率的平方成正比,并且在存储矿物量多于一半时逐渐降低采矿倍率。
此倍率对各种矿物,油井和水的采集都生效。
倍率可以设置为0(默认)此时倍率会随科技解锁而变化默认是100%解锁高级采矿机后变为300%。
- 水的采集速度默认为100/s。
- 能耗:每矿物组 1MW单格水 10MW每油井 1.8MW。
- 燃料格位置。默认星际物流塔和行星内物流塔第4格。设为0则关闭燃料补充能量功能。

View File

@@ -0,0 +1,10 @@
{
"name": "LogisticHub",
"version_number": "0.1.0",
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/LogisticHub",
"description": "Cheat functions to Logistic Storages which make them miner and items hub / 物流塔作弊功能,使其成为矿机和物品枢纽",
"dependencies": [
"xiaoye97-BepInEx-5.4.17",
"soarqin-UXAssist-1.2.0"
]
}

View File

@@ -1,485 +0,0 @@
using System;
using System.Collections.Generic;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Random = UnityEngine.Random;
namespace LogisticMiner;
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
public class LogisticMiner : BaseUnityPlugin
{
private new static readonly BepInEx.Logging.ManualLogSource Logger =
BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME);
private static long _oreEnergyConsume = 2000000;
private static long _oilEnergyConsume = 3600000;
private static long _waterEnergyConsume = 20000000;
private static int _waterSpeed = 100;
private static int _miningScale;
private static int _fuelIlsSlot = 3;
private static int _fuelPlsSlot = 2;
private static float _frame;
private static float _miningCostRateByTech;
private static float _miningSpeedScaleByTech;
private static float _miningFrames;
private static long _miningSpeedScaleLong;
private static bool _advancedMiningMachineUnlocked;
private static uint _miningCostBarrier;
private static uint _miningCostBarrierOil;
private static uint _seed = (uint)Random.Range(int.MinValue, int.MaxValue);
private static readonly Dictionary<int, VeinCacheData> PlanetVeinCacheData = new();
private static readonly Dictionary<int, (long, bool)> Fuels = new();
private bool _cfgEnabled = true;
private void Awake()
{
_cfgEnabled = Config.Bind("General", "Enabled", _cfgEnabled, "enable/disable this plugin").Value;
_oreEnergyConsume = Config.Bind("General", "EnergyConsumptionForOre", _oreEnergyConsume / 2000,
"Energy consumption for each ore vein group(in kW)").Value * 2000;
_oilEnergyConsume = Config.Bind("General", "EnergyConsumptionForOil", _oilEnergyConsume / 2000,
"Energy consumption for each oil seep(in kW)").Value * 2000;
_waterEnergyConsume = Config.Bind("General", "EnergyConsumptionForWater", _waterEnergyConsume / 2000,
"Energy consumption for water slot(in kW)").Value * 2000;
_waterSpeed = Config.Bind("General", "WaterMiningSpeed", _waterSpeed,
"Water mining speed (count per second)").Value;
_miningScale = Config.Bind("General", "MiningScale", _miningScale,
"0 for Auto(which means having researched makes mining scale 300, otherwise 100). Mining scale(in percents) for slots below half of slot limits, and the scale reduces to 100% smoothly till reach full. Please note that the power consumption increases by the square of the scale which is the same as Advanced Mining Machine")
.Value;
_fuelIlsSlot = Config.Bind("General", "ILSFuelSlot", _fuelIlsSlot + 1,
new ConfigDescription("Fuel slot for ILS, set to 0 to disable",
new AcceptableValueRange<int>(0, 5), Array.Empty<object>()))
.Value - 1;
_fuelPlsSlot = Config.Bind("General", "PLSFuelSlot", _fuelPlsSlot + 1,
new ConfigDescription("Fuel slot for PLS, set to 0 to disable",
new AcceptableValueRange<int>(0, 4), Array.Empty<object>()))
.Value - 1;
if (!_cfgEnabled) return;
Harmony.CreateAndPatchAll(typeof(LogisticMiner));
}
private static int SplitIncLevel(ref int n, ref int m, int p)
{
var level = m / n;
var left = m - level * n;
n -= p;
left -= n;
m -= left > 0 ? level * p + left : level * p;
return level;
}
private static void CheckRecipes()
{
_advancedMiningMachineUnlocked = GameMain.history.recipeUnlocked.Contains(119);
}
private static void UpdateMiningCostRate()
{
_miningCostRateByTech = GameMain.history.miningCostRate;
_miningCostBarrier = (uint)(int)Math.Ceiling(2147483646.0 * _miningCostRateByTech);
_miningCostBarrierOil =
(uint)(int)Math.Ceiling(2147483646.0 * _miningCostRateByTech * 0.401116669f /
DSPGame.GameDesc.resourceMultiplier);
}
private static void UpdateSpeedScale()
{
_miningSpeedScaleByTech = GameMain.history.miningSpeedScale;
_miningSpeedScaleLong = (long)(_miningSpeedScaleByTech * 100);
lock (PlanetVeinCacheData)
{
_miningFrames = 120f / _miningSpeedScaleByTech;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(DSPGame), "StartGame", typeof(GameDesc))]
[HarmonyPatch(typeof(DSPGame), "StartGame", typeof(string))]
private static void OnGameStart()
{
Logger.LogInfo("Game Start");
PlanetVeinCacheData.Clear();
Fuels.Clear();
foreach (var data in LDB.items.dataArray)
{
if (data.HeatValue > 0)
{
Fuels.Add(data.ID, (data.HeatValue, data.Productive));
}
}
/* Thinking: storage max may affect mining scale?
_localStationMax = LDB.items.Select(2103).prefabDesc.stationMaxItemCount;
_remoteStationMax = LDB.items.Select(2104).prefabDesc.stationMaxItemCount;
*/
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameMain), "Start")]
private static void OnGameLoaded()
{
_frame = 0f;
UpdateMiningCostRate();
UpdateSpeedScale();
CheckRecipes();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameHistoryData), "UnlockTechFunction")]
private static void OnUnlockTech(int func)
{
switch (func)
{
case 20:
UpdateMiningCostRate();
break;
case 21:
UpdateSpeedScale();
break;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameData), "GameTick")]
private static void FrameTick()
{
var main = GameMain.instance;
if (main.isMenuDemo)
{
return;
}
_frame++;
if (_frame <= 1000000f) return;
/* keep precision of floats by limiting them <= 1000000f */
_frame -= 1000000f;
foreach (var pair in PlanetVeinCacheData)
{
pair.Value.FrameNext -= 1000000f;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameHistoryData), "UnlockRecipe")]
private static void OnUnlockRecipe(int recipeId)
{
if (recipeId == 119)
{
CheckRecipes();
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlanetFactory), "Init")]
[HarmonyPatch(typeof(PlanetFactory), "RecalculateVeinGroup")]
[HarmonyPatch(typeof(PlanetFactory), "RecalculateAllVeinGroups")]
private static void NeedRecalcVeins(PlanetFactory __instance)
{
RecalcVeins(__instance);
}
private static void RecalcVeins(PlanetFactory factory)
{
var planetId = factory.planetId;
lock (PlanetVeinCacheData)
{
/* remove planet veins from dict */
if (PlanetVeinCacheData.TryGetValue(planetId, out var vcd))
{
vcd.GenVeins(factory);
}
else
{
vcd = new VeinCacheData();
vcd.GenVeins(factory);
vcd.FrameNext = _frame + _miningFrames;
PlanetVeinCacheData.Add(planetId, vcd);
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FactorySystem), "CheckBeforeGameTick")]
private static void FactorySystemLogisticMiner(FactorySystem __instance)
{
if (_miningSpeedScaleLong <= 0)
return;
var factory = __instance.factory;
var planetId = factory.planetId;
lock (PlanetVeinCacheData)
{
if (PlanetVeinCacheData.TryGetValue(planetId, out var vcd))
{
if (vcd.FrameNext > _frame)
return;
}
else
{
PlanetVeinCacheData[planetId] = new VeinCacheData
{
FrameNext = _frame + _miningFrames
};
return;
}
var planetTransport = __instance.planet.factory.transport;
var factoryProductionStat =
GameMain.statistics.production.factoryStatPool[__instance.factory.index];
var productRegister = factoryProductionStat?.productRegister;
PerformanceMonitor.BeginSample(ECpuWorkEntry.Miner);
do
{
for (var j = 1; j < planetTransport.stationCursor; j++)
{
var stationComponent = planetTransport.stationPool[j];
if (stationComponent == null) continue;
/* skip Orbital Collectors and Advanced Mining Machines */
if (stationComponent.isCollector || stationComponent.isVeinCollector) continue;
var storage = stationComponent.storage;
if (storage == null) continue;
var isCollecting = false;
for (var k = 0; k < stationComponent.storage.Length; k++)
{
ref var stationStore = ref storage[k];
if (stationStore.localLogic != ELogisticStorage.Demand ||
stationStore.max <= stationStore.count)
continue;
var isVein = vcd.HasVein(stationStore.itemId);
var isVeinOrWater = isVein || stationStore.itemId == __instance.planet.waterItemId;
if (!isVeinOrWater) continue;
int amount;
long energyConsume;
isCollecting = true;
var miningScale = _miningScale;
if (miningScale == 0)
{
miningScale = _advancedMiningMachineUnlocked ? 300 : 100;
}
if (miningScale > 100 && stationStore.count * 2 > stationStore.max)
{
miningScale = 100 +
((miningScale - 100) * (stationStore.max - stationStore.count) * 2 +
stationStore.max - 1) / stationStore.max;
}
if (isVein)
{
(amount, energyConsume) = vcd.Mine(factory, stationStore.itemId, miningScale,
_miningSpeedScaleLong,
stationComponent.energy);
if (amount < 0)
{
k = int.MaxValue - 1;
continue;
}
}
else
{
energyConsume = (_waterEnergyConsume * miningScale * miningScale + 9999L) / 100L /
_miningSpeedScaleLong;
if (stationComponent.energy < energyConsume)
{
k = int.MaxValue - 1;
continue;
}
amount = _waterSpeed * miningScale / 100;
}
if (amount <= 0) continue;
stationStore.count += amount;
if (factoryProductionStat != null)
productRegister[stationStore.itemId] += amount;
stationComponent.energy -= energyConsume;
}
if (!isCollecting || stationComponent.energy * 2 >= stationComponent.energyMax) continue;
var index = stationComponent.isStellar ? _fuelIlsSlot : _fuelPlsSlot;
if (index < 0 || index >= storage.Length)
continue;
var fuelCount = storage[index].count;
if (fuelCount == 0) continue;
if (!Fuels.TryGetValue(storage[index].itemId, out var val) || val.Item1 <= 0)
continue;
/* Sprayed fuels */
int pretendIncLevel;
if (val.Item2 && (pretendIncLevel = storage[index].inc / storage[index].count) > 0)
{
var count = (int)((stationComponent.energyMax - stationComponent.energy) * 1000L /
Cargo.incTable[pretendIncLevel] / 7L);
if (count > fuelCount)
count = fuelCount;
var incLevel = SplitIncLevel(ref storage[index].count, ref storage[index].inc, count);
if (incLevel > 10)
incLevel = 10;
stationComponent.energy += val.Item1 * count * (1000L + Cargo.incTable[incLevel]) / 1000L;
}
else
{
var count = (int)((stationComponent.energyMax - stationComponent.energy) / val.Item1);
if (count > fuelCount)
count = fuelCount;
SplitIncLevel(ref storage[index].count, ref storage[index].inc, count);
stationComponent.energy += val.Item1 * count;
}
}
vcd.FrameNext += _miningFrames;
} while (vcd.FrameNext <= _frame);
PerformanceMonitor.EndSample(ECpuWorkEntry.Miner);
}
}
private class VeinCacheData
{
public float FrameNext;
/* stores list of indices to veinData, with an extra INT which indicates cout of veinGroups at last */
private Dictionary<int, List<int>> _veins = new();
private int _mineIndex = -1;
public bool HasVein(int productId)
{
return _veins.ContainsKey(productId);
}
public void GenVeins(PlanetFactory factory)
{
_veins = new Dictionary<int, List<int>>();
var veinPool = factory.veinPool;
var vg = new Dictionary<int, HashSet<int>>();
for (var i = 0; i < veinPool.Length; i++)
{
if (veinPool[i].amount <= 0 || veinPool[i].type == EVeinType.None) continue;
var productId = veinPool[i].productId;
if (_veins.TryGetValue(productId, out var l))
{
l.Add(i);
}
else
{
_veins.Add(productId, [i]);
}
if (vg.TryGetValue(productId, out var hs))
{
hs.Add(veinPool[i].groupIndex);
}
else
{
vg.Add(productId, [veinPool[i].groupIndex]);
}
}
foreach (var pair in vg)
{
_veins[pair.Key].Add(pair.Value.Count);
}
}
public (int, long) Mine(PlanetFactory factory, int productId, int percent, long miningSpeedScale,
long energyMax)
{
if (!_veins.TryGetValue(productId, out var veins))
{
return (-1, -1L);
}
uint barrier;
int limit;
int count;
long energy;
var length = veins.Count - 1;
/* if is Oil */
if (productId == 1007)
{
energy = (_oilEnergyConsume * length * percent * percent + 9999L) / 100L / miningSpeedScale;
if (energy > energyMax)
return (-1, -1L);
float countf = 0f;
var veinsPool = factory.veinPool;
for (var i = 0; i < length; i++)
{
ref var vd = ref veinsPool[veins[i]];
countf += vd.amount * 4 * VeinData.oilSpeedMultiplier;
}
count = ((int)countf * percent + 99) / 100;
if (count == 0)
return (-1, -1L);
barrier = _miningCostBarrierOil;
limit = 2500;
}
else
{
count = (length * percent + 99) / 100;
if (count == 0)
return (-1, -1L);
energy = (_oreEnergyConsume * veins[length] * percent * percent + 9999L) / 100L / miningSpeedScale;
if (energy > energyMax)
return (-1, -1L);
barrier = _miningCostBarrier;
limit = 0;
}
var veinsData = factory.veinPool;
var total = 0;
for (; count > 0; count--)
{
_mineIndex = (_mineIndex + 1) % length;
var index = veins[_mineIndex];
ref var vd = ref veinsData[index];
int groupIndex;
if (vd.amount > 0)
{
total++;
if (vd.amount > limit)
{
var consume = true;
if (barrier < 2147483646u)
{
_seed = (uint)((int)((ulong)((_seed % 2147483646u + 1) * 48271L) % 2147483647uL) - 1);
consume = _seed < barrier;
}
if (consume)
{
vd.amount--;
groupIndex = vd.groupIndex;
factory.veinGroups[groupIndex].amount--;
if (vd.amount <= 0)
{
factory.veinGroups[groupIndex].count--;
factory.RemoveVeinWithComponents(index);
factory.RecalculateVeinGroup(groupIndex);
if (!_veins.TryGetValue(productId, out veins))
break;
length = veins.Count - 1;
}
}
}
continue;
}
groupIndex = vd.groupIndex;
factory.veinGroups[groupIndex].count--;
factory.RemoveVeinWithComponents(index);
factory.RecalculateVeinGroup(groupIndex);
if (!_veins.TryGetValue(productId, out veins))
break;
length = veins.Count - 1;
}
return (total, energy);
}
}
}

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>LogisticMiner</AssemblyName>
<BepInExPluginGuid>org.soardev.logisticminer</BepInExPluginGuid>
<Description>DSP MOD - LogisticMiner</Description>
<Version>0.1.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
<PackageReference Include="DysonSphereProgram.GameLibs" Version="0.10.32.*-r.*" />
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
</ItemGroup>
</Project>

View File

@@ -1,50 +0,0 @@
# LogisticMiner
#### Logistic Storages can mine all ores/water on current planet
#### 物流塔可以采集当前星球的全部矿产(以及水)
## Usage
* Inspired
by [PlanetMiner](https://dsp.thunderstore.io/package/blacksnipebiu/PlanetMiner)([github](https://github.com/blacksnipebiu/PlanetMiner))
But it is heavily optimized to resolve performance, accuracy and other issues in PlanetMiner.
* (Optimization to PlanetMiner) Only recalculate count of veins when vein chunks are changed (added/removed by foundations/Sandbox-Mode, or
exhausted), so this removes Dictionary allocation on each planet for every frame.
* (Optimization to PlanetMiner) More accurate frame counting by use float number.
* (Optimization to PlanetMiner) Does not increase power consumptions on `Veins Utilization` upgrades.
* (Optimization to PlanetMiner) Separate power consumptions for veins, oil seeps and water.
* (Optimization to PlanetMiner) Power consumptions are counted by groups of veins and count of oil seeps, which is more sensible.
* Can burn fuels in certain slot when energy below half of max.
* (Optimization to PlanetMiner) Sprayed fuels generates extra energy as normal.
* (Optimization to PlanetMiner) All used parameters are configurable:
* Logistic Miner has the same speed as normal Mining Machine for normal ores by default.
But you can set mining scale in configuration, which makes Logistic Miner working like Advance Mining Machines:
power
consumption increases by the square of the scale, and gradually decrease mining speed over half of the maximum
count.
This applies to all of veins, oils and water.
Mining scale can be set to 0(by default), which means it is automatically set by tech unlocks, set to 300 when you
reaches Advanced Mining Machine, otherwise 100.
* 100/s for water by default.
* Energy costs: 1MW/vein-group & 10MW/water-slot & 1.8MW/oil-seep(configurable)
* Fuels burning slot. Default: 4th for ILS, 3rd for PLS. Set to 0 to disable it.
## 使用说明
* 创意来自 [PlanetMiner](https://dsp.thunderstore.io/package/blacksnipebiu/PlanetMiner)([github](https://github.com/blacksnipebiu/PlanetMiner))
对性能重度优化并解决了PlanetMiner的精度等问题。
* (对PlanetMiner的优化) 仅当矿堆发生变化(填埋/恢复/采完)时重新计算矿堆数据,解决每行星每计算帧要重建字典的性能问题。
* (对PlanetMiner的优化) 用浮点数保证更精确的帧计算。
* (对PlanetMiner的优化) 升级`矿物利用`不会提升能耗。
* (对PlanetMiner的优化) 分开矿物,油井和水的采集能耗。
* (对PlanetMiner的优化) 采集能耗以矿物组,油井为单位,相对更加合理。
* 剩余电量少于一半时可以燃烧指定格子的燃料补充。
* (对PlanetMiner的优化) 喷涂了增产剂的燃料按照正常的计算方式提供更多的能量(除了原本就不增加能量输出的反物质燃料棒)。
* (对PlanetMiner的优化) 所有参数都可以在设置文件内配置:
* 物流塔矿机和普通矿机采矿速度一样(等同于同时采集所有对应矿物)。
你可以设置采矿倍率改变物流塔矿机采矿速度,和高级采矿机相同地,能耗和倍率的平方成正比,并且在存储矿物量多于一半时逐渐降低采矿倍率。
此倍率对各种矿物,油井和水的采集都生效。
倍率可以设置为0(默认)此时倍率会随科技解锁而变化默认是100%解锁高级采矿机后变为300%。
* 水的采集速度默认为100/s。
* 能耗:每矿物组 1MW单格水 10MW每油井 1.8MW。
* 燃料格位置。默认星际物流塔第4格行星内物流塔第3格。设为0则关闭燃料补充能量功能。

View File

@@ -1,9 +0,0 @@
{
"name": "LogisticMiner",
"version_number": "0.1.0",
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/LogisticMiner",
"description": "Logistic Storages can mine all ores/water on current planet / 物流塔可以采集当前星球的全部矿产(以及水)",
"dependencies": [
"xiaoye97-BepInEx-5.4.17"
]
}

View File

@@ -9,10 +9,10 @@ Add various cheat functions while disabling abnormal determinants
Moved [to another repo](https://github.com/soarqin/DSP_Mods_TO/tree/master/CompressSave)
## [LogisticMiner](LogisticMiner)
## [LogisticHub](LogisticHub)
Logistic Storages can mine all ores/water on current planet
物流塔可以采集当前星球的全部矿产(以及水)
Cheat functions for Logistic Storages, make them mine resources on the planet and exchange items from certain buildings
物流塔作弊功能,使其可以在星球上采矿并与特定建筑物交换物品
## [HideTips](HideTips)

File diff suppressed because it is too large Load Diff

View File

@@ -131,9 +131,6 @@ public static class WinApi
[DllImport("user32", ExactSpelling = true)]
public static extern IntPtr MonitorFromRect([In] ref Rect lpRect, uint dwFlags);
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
public static extern bool GetProcessAffinityMask(IntPtr hProcess, out ulong lpProcessAffinityMask, out ulong lpSystemAffinityMask);
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
@@ -143,9 +140,6 @@ public static class WinApi
[DllImport("kernel32", ExactSpelling = true)]
public static extern IntPtr GetConsoleWindow();
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
public static extern bool SetProcessAffinityMask(IntPtr hProcess, ulong dwProcessAffinityMask);
// GetPriorityClass and SetPriorityClass
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
public static extern int GetPriorityClass(IntPtr hProcess);
@@ -160,126 +154,4 @@ public static class WinApi
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
#endregion
#region GetLogicalProcessorInformationEx
[Flags]
private enum LOGICAL_PROCESSOR_RELATIONSHIP
{
RelationProcessorCore,
RelationNumaNode,
RelationCache,
RelationProcessorPackage,
RelationGroup,
RelationAll = 0xffff
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct GROUP_AFFINITY
{
public nuint Mask;
public ushort Group;
public ushort Reserved0;
public ushort Reserved1;
public ushort Reserved3;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct PROCESSOR_RELATIONSHIP
{
public byte Flags;
public byte EfficiencyClass;
public ushort Reserved0;
public uint Reserved1;
public uint Reserved2;
public uint Reserved3;
public uint Reserved4;
public ushort Reserved5;
public ushort GroupCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public GROUP_AFFINITY[] GroupMask;
}
[StructLayout(LayoutKind.Sequential)]
private struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
{
public LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
public uint Size;
public PROCESSOR_RELATIONSHIP Processor;
}
[DllImport("kernel32", SetLastError = true)]
private static extern bool GetLogicalProcessorInformationEx(
LOGICAL_PROCESSOR_RELATIONSHIP relationshipType,
IntPtr buffer,
ref uint returnLength
);
public struct LogicalProcessorDetails
{
public int CoreCount;
public int ThreadCount;
public int PerformanceCoreCount;
public int EfficiencyCoreCount;
public ulong PerformanceCoreMask;
public ulong EfficiencyCoreMask;
public bool HybridArchitecture => PerformanceCoreCount > 0 && EfficiencyCoreCount > 0;
}
public static LogicalProcessorDetails GetLogicalProcessorDetails()
{
uint returnLength = 0;
GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, IntPtr.Zero, ref returnLength);
var result = new LogicalProcessorDetails();
if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER) return result;
var ptr = Marshal.AllocHGlobal((int)returnLength);
try
{
if (!GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, ptr, ref returnLength))
return result;
uint offset = 0;
var item = ptr;
while (offset < returnLength)
{
var buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)Marshal.PtrToStructure(item, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX));
offset += buffer.Size;
item += (int)buffer.Size;
if (buffer.Relationship != LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore) continue;
result.CoreCount++;
var mask = buffer.Processor.GroupMask[0].Mask;
var tcount = CountBitsSet(mask);
result.ThreadCount += tcount;
if (buffer.Processor.EfficiencyClass > 0)
{
result.PerformanceCoreCount++;
result.PerformanceCoreMask |= mask;
}
else
{
result.EfficiencyCoreCount++;
result.EfficiencyCoreMask |= mask;
}
}
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return result;
int CountBitsSet(ulong mask)
{
var count = 0;
while (mask != 0)
{
mask &= mask - 1;
count++;
}
return count;
}
}
#endregion
}

View File

@@ -124,7 +124,7 @@ public static class PlanetFunctions
var combatStatId = enemyData.combatStatId;
planet.factory.skillSystem.OnRemovingSkillTarget(combatStatId, planet.factory.skillSystem.combatStats.buffer[combatStatId].originAstroId, ETargetType.CombatStat);
planet.factory.skillSystem.combatStats.Remove(combatStatId);
planet.factory.KillEnemyFinally(player, i, ref CombatStat.empty);
planet.factory.KillEnemyFinally(i, ref CombatStat.empty);
}
planet.factory.enemySystem.Free();
UIRoot.instance.uiGame.dfAssaultTip.ClearAllSpots();

View File

@@ -288,7 +288,7 @@ public static class TechFunctions
{
UnlockTechImmediately(techProto, toLevel, withPrerequisites);
}
history.VarifyTechQueue();
history.VerifyTechQueue();
if (history.currentTech != history.techQueue[0])
{
history.currentTech = history.techQueue[0];

View File

@@ -6,7 +6,7 @@ using System.Linq;
using System.Collections.Generic;
using UXAssist.UI;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UXAssist.Functions;
@@ -322,7 +322,7 @@ public static class UIFunctions
}
I18N.OnInitialized += UpdateI18N;
GameLogic.OnDataLoaded += () =>
GameLogicProc.OnDataLoaded += () =>
{
VeinProto veinProto;
ItemProto itemProto;
@@ -348,7 +348,7 @@ public static class UIFunctions
UpdateI18N();
};
GameLogic.OnGameBegin += () =>
GameLogicProc.OnGameBegin += () =>
{
if (DSPGame.IsMenuDemo) return;
@@ -429,7 +429,7 @@ public static class UIFunctions
OnPlanetScanEnded();
}
};
GameLogic.OnGameEnd += () =>
GameLogicProc.OnGameEnd += () =>
{
_starOrderNames = null;
ShowStarName = null;
@@ -679,18 +679,18 @@ public static class UIFunctions
switch (_cornerComboBoxIndex)
{
case 1:
starUI.nameText.text = String.Format("{0}-{1:0.00}", _starOrderNames[star.index], GetStarDist(star));
starUI.nameText.text = String.Format("{0:00}-{1}-{2:0.00}", star.index + 1, _starOrderNames[star.index], GetStarDist(star));
break;
case 2:
{
var (nongas, total) = GetStarPlanetCount(star);
starUI.nameText.text = String.Format("{0}-{1}-{2}", _starOrderNames[star.index], nongas, total);
starUI.nameText.text = String.Format("{0:00}-{1}-{2}-{3}", star.index + 1, _starOrderNames[star.index], nongas, total);
break;
}
case 3:
{
var (nongas, total) = GetStarPlanetCount(star);
starUI.nameText.text = String.Format("{0}-{1:0.00}-{2}-{3}", _starOrderNames[star.index], GetStarDist(star), nongas, total);
starUI.nameText.text = String.Format("{0:00}-{1}-{2:0.00}-{3}-{4}", star.index + 1, _starOrderNames[star.index], GetStarDist(star), nongas, total);
break;
}
default:

View File

@@ -16,10 +16,7 @@ public static class WindowFunctions
private static IntPtr _oldWndProc = IntPtr.Zero;
private static IntPtr _gameWindowHandle = IntPtr.Zero;
public static WinApi.LogicalProcessorDetails ProcessorDetails { get; private set; }
public static ConfigEntry<int> ProcessPriority;
public static ConfigEntry<int> ProcessAffinity;
private static readonly int[] ProrityFlags =
[
@@ -34,12 +31,6 @@ public static class WindowFunctions
{
if (_initialized) return;
_initialized = true;
I18N.Add("Cores: {0}\nThreads: {1}", "Cores: {0}\nThreads: {1}", "核心数: {0}\n线程数: {1}");
I18N.Add("\nP-Cores: {0}\nE-Cores: {1}", "\nP-Cores: {0}\nE-Cores: {1}", "\n性能核心: {0}\n能效核心: {1}");
I18N.Add("\nPriority: {0}", "\nProcess priority: {0}", "\n进程优先级: {0}");
I18N.Add("\nEnabled CPUs: ", "\nEnabled CPUs: ", "\n使用的CPU: ");
I18N.Add("Unknown", "Unknown", "未知");
ProcessorDetails = WinApi.GetLogicalProcessorDetails();
SetWindowTitle();
}
@@ -54,37 +45,6 @@ public static class WindowFunctions
ProcessPriority.SettingChanged += (_, _) => WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
ProcessAffinity.SettingChanged += (_, _) => UpdateAffinity();
UpdateAffinity();
return;
static void UpdateAffinity()
{
var process = WinApi.GetCurrentProcess();
if (!WinApi.GetProcessAffinityMask(process, out _, out var systemMask))
{
systemMask = ulong.MaxValue;
}
switch (ProcessAffinity.Value)
{
case 0:
WinApi.SetProcessAffinityMask(process, systemMask);
break;
case 1:
WinApi.SetProcessAffinityMask(process, systemMask & ((1UL << (ProcessorDetails.ThreadCount / 2)) - 1UL));
break;
case 2:
WinApi.SetProcessAffinityMask(process, systemMask & (ProcessorDetails.ThreadCount > 16 ? 0xFFUL : 1UL));
break;
case 3:
WinApi.SetProcessAffinityMask(process, systemMask & ProcessorDetails.PerformanceCoreMask);
break;
case 4:
WinApi.SetProcessAffinityMask(process, systemMask & ProcessorDetails.EfficiencyCoreMask);
break;
}
}
}
private static IntPtr GameWndProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam)
@@ -118,50 +78,6 @@ public static class WindowFunctions
};
}
public static void ShowCPUInfo()
{
var details = ProcessorDetails;
var msg = string.Format("Cores: {0}\nThreads: {1}".Translate(), details.CoreCount, details.ThreadCount);
var hybrid = details.HybridArchitecture;
if (hybrid)
{
msg += string.Format("\nP-Cores: {0}\nE-Cores: {1}".Translate(), details.PerformanceCoreCount, details.EfficiencyCoreCount);
}
var handle = WinApi.GetCurrentProcess();
var prio = GetPriorityName(WinApi.GetPriorityClass(handle));
msg += string.Format("\nPriority: {0}".Translate(), prio);
var aff = 0UL;
if (WinApi.GetProcessAffinityMask(handle, out var processMask, out var systemMask))
aff = processMask & systemMask;
msg += "\nEnabled CPUs: ".Translate();
var first = true;
for (var i = 0; aff != 0UL; i++)
{
if ((aff & 1UL) != 0)
{
if (first)
first = false;
else
msg += ",";
msg += i;
if (hybrid)
{
if ((details.PerformanceCoreMask & (1UL << i)) != 0)
msg += "(P)";
else if ((details.EfficiencyCoreMask & (1UL << i)) != 0)
msg += "(E)";
}
}
aff >>= 1;
}
UIMessageBox.Show("CPU Info".Translate(), msg, "确定".Translate(), -1);
}
public static void SetWindowTitle()
{
// Get profile name from command line arguments, and set window title accordingly

View File

@@ -0,0 +1,23 @@
using HarmonyLib;
namespace UXAssist.ModsCompat;
class PlanetVeinUtilization
{
public const string PlanetVeinUtilizationGuid = "testpostpleaseignore.dsp.planet_vein_utilization";
public static bool Run(Harmony harmony)
{
if (!BepInEx.Bootstrap.Chainloader.PluginInfos.TryGetValue(PlanetVeinUtilizationGuid, out var pluginInfo)) return false;
var assembly = pluginInfo.Instance.GetType().Assembly;
var classType = assembly.GetType("PlanetVeinUtilization.PlanetVeinUtilization");
harmony.Patch(AccessTools.Method(classType, "Awake"),
new HarmonyMethod(typeof(PlanetVeinUtilization).GetMethod("PatchPlanetVeinUtilizationAwake")));
return true;
}
public static bool PatchPlanetVeinUtilizationAwake()
{
return false;
}
}

View File

@@ -5,7 +5,7 @@ using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine.UI;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UXAssist.Patches;
@@ -269,14 +269,14 @@ public class DysonSpherePatch : PatchImpl<DysonSpherePatch>
protected override void OnEnable()
{
InitNodeForAbsorb();
GameLogic.OnGameBegin += GameMain_Begin_Postfix;
GameLogic.OnGameEnd += GameMain_End_Postfix;
GameLogicProc.OnGameBegin += GameMain_Begin_Postfix;
GameLogicProc.OnGameEnd += GameMain_End_Postfix;
}
protected override void OnDisable()
{
GameLogic.OnGameEnd -= GameMain_End_Postfix;
GameLogic.OnGameBegin -= GameMain_Begin_Postfix;
GameLogicProc.OnGameEnd -= GameMain_End_Postfix;
GameLogicProc.OnGameBegin -= GameMain_Begin_Postfix;
_initialized = false;
_nodeForAbsorb = null;
}

View File

@@ -10,7 +10,7 @@ using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UXAssist.Patches;
@@ -276,12 +276,12 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
protected override void OnEnable()
{
GameLogic.OnGameEnd += GameMain_End_Postfix;
GameLogicProc.OnGameEnd += GameMain_End_Postfix;
}
protected override void OnDisable()
{
GameLogic.OnGameEnd -= GameMain_End_Postfix;
GameLogicProc.OnGameEnd -= GameMain_End_Postfix;
if (_sunlight)
{
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
@@ -359,7 +359,7 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(StarSimulator), "LateUpdate")]
[HarmonyPatch(typeof(StarSimulator), nameof(StarSimulator.LateUpdate))]
private static IEnumerable<CodeInstruction> StarSimulator_LateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
@@ -385,7 +385,7 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(PlanetSimulator), "LateUpdate")]
[HarmonyPatch(typeof(PlanetSimulator), nameof(PlanetSimulator.LateUpdate))]
private static IEnumerable<CodeInstruction> PlanetSimulator_LateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
// var vec = (NightlightEnabled ? GameMain.mainPlayer.transform.up : (Quaternion.Inverse(localPlanet.runtimeRotation) * (__instance.planetData.star.uPosition - __instance.planetData.uPosition).normalized));
@@ -1150,7 +1150,7 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
var pos = veinPool[veinId].pos;
factory.RemoveVeinWithComponents(veinId);
factory.RecalculateVeinGroup(groupIndex);
factory.NotifyVeinExhausted(venType, pos);
factory.NotifyVeinExhausted(venType, groupIndex, pos);
veinCount = __instance.veinCount;
}
else
@@ -1251,7 +1251,7 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
factory.veinAnimPool[veinId].time = amount >= 25000 ? 0f : 1f - amount * VeinData.oilSpeedMultiplier;
if (amount <= 2500)
{
factory.NotifyVeinExhausted((int)veinPool[veinId].type, veinPool[veinId].pos);
factory.NotifyVeinExhausted((int)veinPool[veinId].type, groupIndex, veinPool[veinId].pos);
}
}
}
@@ -1401,20 +1401,20 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
{
private static readonly List<bool> OldDragBuild = [];
private static readonly List<Vector2> OldDragBuildDist = [];
private static readonly int[] PowerPoleIds = [2201, 2202, 2212];
private static readonly int[] PowerPoleIds = [2202, 2212];
protected override void OnEnable()
{
GameLogic.OnGameBegin += GameMain_Begin_Postfix;
GameLogic.OnGameEnd += GameMain_End_Postfix;
GameLogicProc.OnGameBegin += GameMain_Begin_Postfix;
GameLogicProc.OnGameEnd += GameMain_End_Postfix;
FixProto();
}
protected override void OnDisable()
{
UnfixProto();
GameLogic.OnGameEnd -= GameMain_End_Postfix;
GameLogic.OnGameBegin -= GameMain_Begin_Postfix;
GameLogicProc.OnGameEnd -= GameMain_End_Postfix;
GameLogicProc.OnGameBegin -= GameMain_Begin_Postfix;
}
public static void AlternatelyChanged()
@@ -1435,13 +1435,13 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
OldDragBuildDist.Clear();
foreach (var id in PowerPoleIds)
{
var powerPole = LDB.items.Select(id);
if (powerPole?.prefabDesc == null) return;
OldDragBuild.Add(powerPole.prefabDesc.dragBuild);
OldDragBuildDist.Add(powerPole.prefabDesc.dragBuildDist);
powerPole.prefabDesc.dragBuild = true;
var distance = (id == 2201 && DragBuildPowerPolesAlternatelyEnabled.Value ? LDB.items.Select(2202) : powerPole).prefabDesc.powerConnectDistance - 0.72f;
powerPole.prefabDesc.dragBuildDist = new Vector2(distance, distance);
var prefabDesc = LDB.items.Select(id)?.prefabDesc;
if (prefabDesc == null) return;
OldDragBuild.Add(prefabDesc.dragBuild);
OldDragBuildDist.Add(prefabDesc.dragBuildDist);
prefabDesc.dragBuild = true;
var distance = prefabDesc.powerConnectDistance - 0.72f;
prefabDesc.dragBuildDist = new Vector2(distance, distance);
}
}
@@ -1509,13 +1509,13 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
return finalCount;
}
private static int PlanetAuxDataSnapDotsNonAllocNotAligned(PlanetAuxData aux, Vector3 begin, Vector3 end, Vector2 interval, float yaw, float gap, Vector3[] snaps)
private static int PlanetAuxDataSnapDotsNonAllocNotAligned(PlanetAuxData aux, Vector3 begin, Vector3 end, Vector2 interval, float height, float yaw, float gap, Vector3[] snaps)
{
var num = 0;
var magnitude = begin.magnitude;
if (aux.activeGrid != null)
{
num = PlanetGridSnapDotsNonAllocNotAligned(aux.activeGrid, begin, end, interval, yaw, aux.planet.realRadius, gap, snaps);
num = PlanetGridSnapDotsNonAllocNotAligned(aux.activeGrid, begin, end, interval, yaw, aux.planet.realRadius + height, gap, snaps);
for (var i = 0; i < num; i++)
{
snaps[i] *= magnitude;
@@ -1560,17 +1560,28 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BuildTool_Click), nameof(BuildTool_Click.handPrefabDesc))),
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(BuildPreview), nameof(BuildPreview.desc)))
).Advance(2).InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 6)).SetInstructionAndAdvance(Transpilers.EmitDelegate((BuildTool_Click click, int i) =>
);
var pos = matcher.Pos;
matcher.MatchBack(false,
new CodeMatch(ci => ci.IsLdloc()),
new CodeMatch(ci => ci.IsLdloc()),
new CodeMatch(OpCodes.Mul),
new CodeMatch(ci => ci.IsLdloc()),
new CodeMatch(OpCodes.Add)
);
var operand = matcher.Operand;
matcher.Start().Advance(pos);
matcher.Advance(2).InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, operand)).SetInstructionAndAdvance(Transpilers.EmitDelegate((BuildTool_Click click, int i) =>
{
if (!DragBuildPowerPolesAlternatelyEnabled.Value || (i & 1) == 0) return click.handItem;
var id = click.handItem.ID;
if (id != 2201 && id != 2202) return click.handItem;
if (id != 2202) return click.handItem;
return LDB.items.Select(id ^ 3);
})).Advance(3).InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 6)).SetInstructionAndAdvance(Transpilers.EmitDelegate((BuildTool_Click click, int i) =>
})).Advance(3).InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, operand)).SetInstructionAndAdvance(Transpilers.EmitDelegate((BuildTool_Click click, int i) =>
{
if (!DragBuildPowerPolesAlternatelyEnabled.Value || (i & 1) == 0) return click.handPrefabDesc;
var id = click.handItem.ID;
if (id != 2201 && id != 2202) return click.handPrefabDesc;
if (id != 2202) return click.handPrefabDesc;
return LDB.items.Select(id ^ 3).prefabDesc;
}));
return matcher.InstructionEnumeration();
@@ -1770,14 +1781,14 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
protected override void OnEnable()
{
AddBeltSignalProtos();
GameLogic.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
GameLogic.OnGameBegin += GameMain_Begin_Postfix;
GameLogicProc.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
GameLogicProc.OnGameBegin += GameMain_Begin_Postfix;
}
protected override void OnDisable()
{
GameLogic.OnGameBegin -= GameMain_Begin_Postfix;
GameLogic.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
GameLogicProc.OnGameBegin -= GameMain_Begin_Postfix;
GameLogicProc.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
}
private static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
@@ -1833,91 +1844,82 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(GameData), "GameTick")]
public static IEnumerable<CodeInstruction> GameData_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
[HarmonyPostfix]
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.OnFactoryFrameBegin))]
public static void GameLogic_OnFactoryFrameBegin_Postfix()
{
var matcher = new CodeMatcher(instructions, generator);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(PerformanceMonitor), nameof(PerformanceMonitor.EndSample)))
).Advance(1).Insert(
Transpilers.EmitDelegate(() =>
var factories = GameMain.data?.factories;
if (factories == null) return;
var factoriesCount = factories.Length;
var propertySystem = DSPGame.propertySystem;
List<int> factoriesToRemove = null;
foreach (var factoryIndex in SignalBeltFactoryIndices)
{
if (factoryIndex >= factoriesCount)
{
var factories = GameMain.data?.factories;
if (factories == null) return;
var factoriesCount = factories.Length;
var propertySystem = DSPGame.propertySystem;
List<int> factoriesToRemove = null;
foreach (var factoryIndex in SignalBeltFactoryIndices)
if (factoriesToRemove == null)
factoriesToRemove = [factoryIndex];
else
factoriesToRemove.Add(factoryIndex);
continue;
}
var signalBelts = GetSignalBelts(factoryIndex);
if (signalBelts == null) continue;
var factory = factories[factoryIndex];
if (factory == null) continue;
var cargoTraffic = factory.cargoTraffic;
var beltCount = cargoTraffic.beltCursor;
List<int> beltsToRemove = null;
foreach (var kvp in signalBelts)
{
if (kvp.Key >= beltCount)
{
if (factoryIndex >= factoriesCount)
{
if (factoriesToRemove == null)
factoriesToRemove = [factoryIndex];
else
factoriesToRemove.Add(factoryIndex);
continue;
}
var signalBelts = GetSignalBelts(factoryIndex);
if (signalBelts == null) continue;
var factory = factories[factoryIndex];
if (factory == null) continue;
var cargoTraffic = factory.cargoTraffic;
var beltCount = cargoTraffic.beltCursor;
List<int> beltsToRemove = null;
foreach (var kvp in signalBelts)
{
if (kvp.Key >= beltCount)
{
if (beltsToRemove == null)
beltsToRemove = [kvp.Key];
else
beltsToRemove.Add(kvp.Key);
continue;
}
ref var belt = ref cargoTraffic.beltPool[kvp.Key];
var cargoPath = cargoTraffic.GetCargoPath(belt.segPathId);
var itemIdx = kvp.Value;
if (cargoPath == null) continue;
var itemId = DarkFogItemIds[itemIdx];
var consume = (byte)Math.Min(DarkFogItemsInVoid[itemIdx], 4);
if (consume < 4)
{
var metaverse = propertySystem.GetItemAvaliableProperty(_clusterSeedKey, 6006);
if (metaverse > 0)
{
if (metaverse > 10)
metaverse = 10;
propertySystem.AddItemConsumption(_clusterSeedKey, 6006, metaverse);
var mainPlayer = GameMain.mainPlayer;
GameMain.history.AddPropertyItemConsumption(6006, metaverse, true);
var count = DarkFogItemExchangeRate[itemIdx] * metaverse;
DarkFogItemsInVoid[itemIdx] += count;
consume = (byte)Math.Min(DarkFogItemsInVoid[itemIdx], 4);
mainPlayer.mecha.AddProductionStat(itemId, count, mainPlayer.nearestFactory);
}
}
if (consume > 0 && cargoPath.TryInsertItem(belt.segIndex + belt.segPivotOffset, itemId, consume, 0))
DarkFogItemsInVoid[itemIdx] -= consume;
}
if (beltsToRemove == null) continue;
foreach (var beltId in beltsToRemove)
signalBelts.Remove(beltId);
if (signalBelts.Count > 0) continue;
if (factoriesToRemove == null)
factoriesToRemove = [factoryIndex];
if (beltsToRemove == null)
beltsToRemove = [kvp.Key];
else
factoriesToRemove.Add(factoryIndex);
beltsToRemove.Add(kvp.Key);
continue;
}
if (factoriesToRemove == null) return;
foreach (var factoryIndex in factoriesToRemove)
ref var belt = ref cargoTraffic.beltPool[kvp.Key];
var cargoPath = cargoTraffic.GetCargoPath(belt.segPathId);
var itemIdx = kvp.Value;
if (cargoPath == null) continue;
var itemId = DarkFogItemIds[itemIdx];
var consume = (byte)Math.Min(DarkFogItemsInVoid[itemIdx], 4);
if (consume < 4)
{
RemovePlanetSignalBelts(factoryIndex);
var metaverse = propertySystem.GetItemAvaliableProperty(_clusterSeedKey, 6006);
if (metaverse > 0)
{
if (metaverse > 10)
metaverse = 10;
propertySystem.AddItemConsumption(_clusterSeedKey, 6006, metaverse);
var mainPlayer = GameMain.mainPlayer;
GameMain.history.AddPropertyItemConsumption(6006, metaverse, true);
var count = DarkFogItemExchangeRate[itemIdx] * metaverse;
DarkFogItemsInVoid[itemIdx] += count;
consume = (byte)Math.Min(DarkFogItemsInVoid[itemIdx], 4);
mainPlayer.mecha.AddProductionStat(itemId, count, mainPlayer.nearestFactory);
}
}
})
);
return matcher.InstructionEnumeration();
if (consume > 0 && cargoPath.TryInsertItem(belt.segIndex + belt.segPivotOffset, itemId, consume, 0))
DarkFogItemsInVoid[itemIdx] -= consume;
}
if (beltsToRemove == null) continue;
foreach (var beltId in beltsToRemove)
signalBelts.Remove(beltId);
if (signalBelts.Count > 0) continue;
if (factoriesToRemove == null)
factoriesToRemove = [factoryIndex];
else
factoriesToRemove.Add(factoryIndex);
}
if (factoriesToRemove == null) return;
foreach (var factoryIndex in factoriesToRemove)
{
RemovePlanetSignalBelts(factoryIndex);
}
}
}

View File

@@ -19,8 +19,6 @@ public class GamePatch : PatchImpl<GamePatch>
public static ConfigEntry<bool> EnableWindowResizeEnabled;
public static ConfigEntry<bool> LoadLastWindowRectEnabled;
public static ConfigEntry<int> MouseCursorScaleUpMultiplier;
// public static ConfigEntry<bool> AutoSaveOptEnabled;
public static ConfigEntry<bool> ConvertSavesFromPeaceEnabled;
public static ConfigEntry<Vector4> LastWindowRect;
@@ -87,11 +85,6 @@ public class GamePatch : PatchImpl<GamePatch>
FixLastWindowRect();
}
};
MouseCursorScaleUpMultiplier.SettingChanged += (_, _) =>
{
MouseCursorScaleUp.NeedReloadCursors = true;
MouseCursorScaleUp.Enable(MouseCursorScaleUpMultiplier.Value > 1);
};
// AutoSaveOptEnabled.SettingChanged += (_, _) => AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
ConvertSavesFromPeaceEnabled.SettingChanged += (_, _) => ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
ProfileBasedSaveFolderEnabled.SettingChanged += (_, _) => RefreshSavePath();
@@ -123,8 +116,6 @@ public class GamePatch : PatchImpl<GamePatch>
}
}
EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
MouseCursorScaleUp.NeedReloadCursors = false;
MouseCursorScaleUp.Enable(MouseCursorScaleUpMultiplier.Value > 1);
// AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
Enable(true);
@@ -136,8 +127,6 @@ public class GamePatch : PatchImpl<GamePatch>
{
Enable(false);
EnableWindowResize.Enable(false);
MouseCursorScaleUp.NeedReloadCursors = false;
MouseCursorScaleUp.Enable(false);
// AutoSaveOpt.Enable(false);
ConvertSavesFromPeace.Enable(false);
}
@@ -160,7 +149,7 @@ public class GamePatch : PatchImpl<GamePatch>
[HarmonyPostfix]
[HarmonyPriority(Priority.First)]
[HarmonyPatch(typeof(GameConfig), "gameSaveFolder", MethodType.Getter)]
[HarmonyPatch(typeof(GameConfig), nameof(GameConfig.gameSaveFolder), MethodType.Getter)]
public static void GameConfig_gameSaveFolder_Postfix(ref string __result)
{
if (!ProfileBasedSaveFolderEnabled.Value || string.IsNullOrEmpty(WindowFunctions.ProfileName)) return;
@@ -231,7 +220,7 @@ public class GamePatch : PatchImpl<GamePatch>
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(int))]
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(RefreshRate))]
private static void Screen_SetResolution_Prefix(ref int width, ref int height, FullScreenMode fullscreenMode, ref Vector2Int __state)
{
if (fullscreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow) return;
@@ -258,7 +247,7 @@ public class GamePatch : PatchImpl<GamePatch>
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(int))]
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(RefreshRate))]
private static void Screen_SetResolution_Postfix(FullScreenMode fullscreenMode, Vector2Int __state)
{
if (fullscreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow) return;
@@ -282,36 +271,6 @@ public class GamePatch : PatchImpl<GamePatch>
ThreadingHelper.Instance.StartCoroutine(SetWindowPositionCoroutine(wnd, x, y));
}
private static GameOption _gameOption;
[HarmonyPostfix]
[HarmonyPatch(typeof(UIOptionWindow), nameof(UIOptionWindow._OnOpen))]
private static void UIOptionWindow__OnOpen_Postfix()
{
_gameOption = DSPGame.globalOption;
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(GameOption), nameof(GameOption.Apply))]
private static IEnumerable<CodeInstruction> UIOptionWindow_ApplyOptions_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
var label1 = generator.DefineLabel();
matcher.MatchForward(false,
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(Screen), nameof(Screen.SetResolution), [typeof(int), typeof(int), typeof(bool), typeof(int)]))
).Advance(1).Labels.Add(label1);
matcher.Start().Insert(
Transpilers.EmitDelegate(() =>
_gameOption.fullscreen == DSPGame.globalOption.fullscreen &&
_gameOption.resolution.width == DSPGame.globalOption.resolution.width &&
_gameOption.resolution.height == DSPGame.globalOption.resolution.height &&
_gameOption.resolution.refreshRate == DSPGame.globalOption.resolution.refreshRate
),
new CodeInstruction(OpCodes.Brtrue, label1)
);
return matcher.InstructionEnumeration();
}
private class EnableWindowResize : PatchImpl<EnableWindowResize>
{
private static bool _enabled;
@@ -601,131 +560,4 @@ public class GamePatch : PatchImpl<GamePatch>
return false;
}
}
[PatchSetCallbackFlag(PatchCallbackFlag.CallOnDisableAfterUnpatch)]
private class MouseCursorScaleUp : PatchImpl<MouseCursorScaleUp>
{
public static bool NeedReloadCursors;
protected override void OnEnable()
{
if (!NeedReloadCursors) return;
if (!UICursor.loaded) return;
UICursor.loaded = false;
UICursor.LoadCursors();
}
protected override void OnDisable()
{
if (!NeedReloadCursors) return;
if (!UICursor.loaded) return;
UICursor.loaded = false;
UICursor.LoadCursors();
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(UICursor), nameof(UICursor.LoadCursors))]
private static IEnumerable<CodeInstruction> UICursor_LoadCursors_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
/*
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldc_I4_S),
new CodeMatch(OpCodes.Newarr)
);
var startPos = matcher.Pos;
matcher.Advance(2).MatchForward(false,
new CodeMatch(OpCodes.Stsfld, AccessTools.Field(typeof(UICursor), nameof(UICursor.cursorTexs)))
);
var endPos = matcher.Pos + 1;
matcher.Start().Advance(startPos).RemoveInstructions(endPos - startPos);
matcher.InsertAndAdvance(
Transpilers.EmitDelegate(() =>
{
var pluginfolder = Util.PluginFolder;
UICursor.cursorTexs =
[
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-transfer.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-target-in.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-target-out.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-target-a.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-target-b.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-ban.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-delete.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-reform.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-dyson-node-create.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-painter.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-eyedropper.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-eraser.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-upgrade.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-downgrade.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-blank.png"),
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-remove.png")
];
})
);
*/
matcher.MatchForward(false,
new CodeMatch(OpCodes.Stsfld, AccessTools.Field(typeof(UICursor), nameof(UICursor.cursorHots))),
new CodeMatch(OpCodes.Ldc_I4_1),
new CodeMatch(OpCodes.Stsfld, AccessTools.Field(typeof(UICursor), nameof(UICursor.loaded)))
).Advance(1).InsertAndAdvance(
Transpilers.EmitDelegate(() =>
{
var multiplier = MouseCursorScaleUpMultiplier.Value;
for (var i = 0; i < UICursor.cursorTexs.Length; i++)
{
var cursor = UICursor.cursorTexs[i];
if (cursor == null) continue;
var newWidth = 32 * multiplier;
var newHeight = 32 * multiplier;
if (cursor.width == newWidth && cursor.height == newHeight) continue;
UICursor.cursorTexs[i] = ResizeTexture2D(cursor, newWidth, newHeight);
}
if (multiplier <= 1) return;
for (var i = UICursor.cursorHots.Length - 1; i >= 0; i--)
{
UICursor.cursorHots[i] = new Vector2(UICursor.cursorHots[i].x * multiplier, UICursor.cursorHots[i].y * multiplier);
}
})
).MatchForward(false,
new CodeMatch(OpCodes.Ldc_I4_0),
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(Cursor), nameof(Cursor.SetCursor), [typeof(Texture2D), typeof(Vector2), typeof(CursorMode)]))
).SetInstruction(new CodeInstruction(OpCodes.Ldc_I4_1));
return matcher.InstructionEnumeration();
Texture2D ResizeTexture2D(Texture2D texture2D, int targetWidth, int targetHeight)
{
var oldActive = RenderTexture.active;
var rt = new RenderTexture(targetWidth, targetHeight, 32)
{
antiAliasing = 8
};
RenderTexture.active = rt;
Graphics.Blit(texture2D, rt);
rt.ResolveAntiAliasedSurface();
var result = new Texture2D(targetWidth, targetHeight, texture2D.format, false);
result.ReadPixels(new Rect(0, 0, targetWidth, targetHeight), 0, 0);
result.filterMode = FilterMode.Trilinear;
result.Apply();
RenderTexture.active = oldActive;
rt.Release();
return result;
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(UICursor), nameof(UICursor.cursorIndexApply), MethodType.Setter)]
private static IEnumerable<CodeInstruction> UICursor_set_cursorIndexApply_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
matcher.Start().MatchForward(false,
new CodeMatch(OpCodes.Ldc_I4_0),
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(Cursor), nameof(Cursor.SetCursor), [typeof(Texture2D), typeof(Vector2), typeof(CursorMode)]))
).SetInstruction(new CodeInstruction(OpCodes.Ldc_I4_1));
return matcher.InstructionEnumeration();
}
}
}

View File

@@ -9,8 +9,8 @@ using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using Object = UnityEngine.Object;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UXAssist.Patches;
@@ -74,14 +74,14 @@ public static class LogisticsPatch
RealtimeLogisticsInfoPanel.Enable(RealtimeLogisticsInfoPanelEnabled.Value);
RealtimeLogisticsInfoPanel.EnableBars(RealtimeLogisticsInfoPanelBarsEnabled.Value);
GameLogic.OnGameBegin += RealtimeLogisticsInfoPanel.OnGameBegin;
GameLogic.OnDataLoaded += RealtimeLogisticsInfoPanel.OnDataLoaded;
GameLogicProc.OnGameBegin += RealtimeLogisticsInfoPanel.OnGameBegin;
GameLogicProc.OnDataLoaded += RealtimeLogisticsInfoPanel.OnDataLoaded;
}
public static void Uninit()
{
GameLogic.OnDataLoaded -= RealtimeLogisticsInfoPanel.OnDataLoaded;
GameLogic.OnGameBegin -= RealtimeLogisticsInfoPanel.OnGameBegin;
GameLogicProc.OnDataLoaded -= RealtimeLogisticsInfoPanel.OnDataLoaded;
GameLogicProc.OnGameBegin -= RealtimeLogisticsInfoPanel.OnGameBegin;
AutoConfigLogistics.Enable(false);
AutoConfigLogisticsSetDefaultRemoteLogicToStorage.Enable(false);
@@ -719,6 +719,7 @@ public static class LogisticsPatch
{
private static StationTip[] _stationTips = new StationTip[16];
private static readonly StationTip[] StationTipsRecycle = new StationTip[128];
private static readonly Sprite[] StateSprite = [null, null, null];
private static int _stationTipsRecycleCount;
private static GameObject _stationTipsRoot;
private static GameObject _tipPrefab;
@@ -727,7 +728,7 @@ public static class LogisticsPatch
private static readonly Color OrderInColor = new(108f / 255, 187f / 255, 214f / 255);
private static readonly Color OrderOutColor = new(255f / 255, 161f / 255, 109.5f / 255);
private static PlanetData _lastPlanet;
private static int _lastPlanetId;
private static int _localStorageMax = 5000;
private static int _remoteStorageMax = 10000;
@@ -769,12 +770,19 @@ public static class LogisticsPatch
if (_stationTipsRoot == null) return;
if (!on)
{
RecycleStationTips();
_lastPlanetId = 0;
_stationTipsRoot.SetActive(false);
return;
}
if (DSPGame.IsMenuDemo || !GameMain.isRunning) return;
_lastPlanet = GameMain.localPlanet;
_stationTipsRoot.SetActive(on && _lastPlanet != null);
if (DSPGame.IsMenuDemo || !GameMain.isRunning)
{
_lastPlanetId = 0;
_stationTipsRoot.SetActive(false);
return;
}
_lastPlanetId = GameMain.data?.localPlanet?.id ?? 0;
_stationTipsRoot.SetActive(_lastPlanetId != 0);
}
public static void EnableBars(bool on)
@@ -788,7 +796,9 @@ public static class LogisticsPatch
public static void OnGameBegin()
{
_lastPlanet = null;
RecycleStationTips();
_lastPlanetId = 0;
_stationTipsRoot?.SetActive(false);
}
public static void OnDataLoaded()
@@ -842,7 +852,7 @@ public static class LogisticsPatch
var sliderBgPrefab = GameObject.Find("UI Root/Overlay Canvas/In Game/Windows/Station Window/storage-box-0/slider-bg");
_tipPrefab = Object.Instantiate(GameObject.Find("UI Root/Overlay Canvas/In Game/Scene UIs/Vein Marks/vein-tip-prefab"), _stationTipsRoot.transform);
_tipPrefab = Object.Instantiate(GameObject.Find("UI Root/Overlay Canvas/In Game/Scene UIs/Vein Marks/vein-tips/vein-tip-prefab"), _stationTipsRoot.transform);
_tipPrefab.name = "tipPrefab";
Object.Destroy(_tipPrefab.GetComponent<UIVeinDetailNode>());
var image = _tipPrefab.GetComponent<Image>();
@@ -993,6 +1003,11 @@ public static class LogisticsPatch
tipIconPrefab.gameObject.SetActive(false);
_tipPrefab.SetActive(false);
_stationTipsRoot.SetActive(false);
StateSprite[0] = Util.LoadEmbeddedSprite("assets/icon/keep.png");
StateSprite[1] = Util.LoadEmbeddedSprite("assets/icon/out.png");
StateSprite[2] = Util.LoadEmbeddedSprite("assets/icon/in.png");
}
private static void RecycleStationTips()
@@ -1012,9 +1027,27 @@ public static class LogisticsPatch
}
}
Array.Resize(ref _stationTips, 16);
Array.Clear(_stationTips, 0, _stationTips.Length);
}
private static void RecycleStationTip(int index)
{
var stationTip = _stationTips[index];
if (!stationTip) return;
if (_stationTipsRecycleCount < 128)
{
stationTip.ResetStationTip();
stationTip.gameObject.SetActive(false);
StationTipsRecycle[_stationTipsRecycleCount++] = stationTip;
}
else
{
Object.Destroy(stationTip);
}
_stationTips[index] = null;
}
private static StationTip AllocateStationTip()
{
if (_stationTipsRecycleCount > 0)
@@ -1033,21 +1066,31 @@ public static class LogisticsPatch
public static void StationInfoPanelsUpdate()
{
if (DSPGame.IsMenuDemo || !GameMain.isRunning) return;
var localPlanet = GameMain.localPlanet;
if (localPlanet == null)
var localPlanet = GameMain.data?.localPlanet;
if (localPlanet == null || !localPlanet.factoryLoaded)
{
_stationTipsRoot.SetActive(false);
if (_lastPlanetId == 0) return;
RecycleStationTips();
_lastPlanetId = 0;
return;
}
if (_lastPlanetId != localPlanet.id)
{
RecycleStationTips();
_lastPlanetId = localPlanet.id;
}
var factory = localPlanet.factory;
var transport = factory?.transport;
if (transport is not { stationCursor: > 1 } || (UIGame.viewMode != EViewMode.Normal && UIGame.viewMode != EViewMode.Globe))
{
if (_lastPlanet == null) return;
_lastPlanet = null;
_stationTipsRoot.SetActive(false);
return;
}
if (_lastPlanet != localPlanet)
{
RecycleStationTips();
_lastPlanet = localPlanet;
}
_stationTipsRoot.SetActive(true);
if (UpdateStorageMax())
{
foreach (var tip in _stationTips)
@@ -1056,26 +1099,14 @@ public static class LogisticsPatch
}
}
var factory = localPlanet.factory;
var transport = factory?.transport;
if (transport is not { stationCursor: > 1 } || (UIGame.viewMode != EViewMode.Normal && UIGame.viewMode != EViewMode.Globe))
{
if (_stationTipsRoot.activeSelf)
{
_stationTipsRoot.SetActive(false);
}
return;
}
_stationTipsRoot.SetActive(true);
var localPosition = GameCamera.main.transform.localPosition;
var forward = GameCamera.main.transform.forward;
var realRadius = localPlanet.realRadius;
var stationCount = transport.stationCursor;
if (stationCount >= _stationTips.Length)
if (stationCount > _stationTips.Length)
{
var newSize = stationCount;
var newSize = stationCount - 1;
newSize |= newSize >> 1;
newSize |= newSize >> 2;
newSize |= newSize >> 4;
@@ -1088,21 +1119,24 @@ public static class LogisticsPatch
for (var i = stationCount - 1; i > 0; i--)
{
var stationComponent = transport.stationPool[i];
var storageArray = stationComponent?.storage;
if (stationComponent == null || i != stationComponent.id)
{
RecycleStationTip(i);
continue;
}
var storageArray = stationComponent.storage;
if (storageArray == null)
{
_stationTips[i]?.gameObject.SetActive(false);
RecycleStationTip(i);
continue;
}
#if DEBUG
if (i != stationComponent.id)
var stationTip = _stationTips[i];
if (!stationTip)
{
UXAssist.Logger.LogWarning($"Station index mismatch: {i} != {stationComponent.id}");
_stationTips[i]?.gameObject.SetActive(false);
continue;
stationTip = AllocateStationTip();
_stationTips[i] = stationTip;
}
#endif
var position = factory.entityPool[stationComponent.entityId].pos.normalized;
var radius = realRadius;
@@ -1135,17 +1169,10 @@ public static class LogisticsPatch
|| Phys.RayCastSphere(localPosition, vec / magnitude, magnitude, Vector3.zero, realRadius, out _)
|| storageArray.Select(x => x.itemId).All(x => x == 0))
{
_stationTips[i]?.gameObject.SetActive(false);
stationTip.gameObject.SetActive(false);
continue;
}
var stationTip = _stationTips[i];
if (!stationTip)
{
stationTip = AllocateStationTip();
_stationTips[i] = stationTip;
}
stationTip.gameObject.SetActive(true);
var localScaleMultiple = magnitude switch
@@ -1165,7 +1192,6 @@ public static class LogisticsPatch
}
}
public class StationTip : MonoBehaviour
{
[FormerlySerializedAs("RectTransform")]
@@ -1209,13 +1235,6 @@ public static class LogisticsPatch
public ELogisticStorage RemoteState;
}
private static readonly Sprite[] StateSprite =
[
Util.LoadEmbeddedSprite("assets/icon/keep.png"),
Util.LoadEmbeddedSprite("assets/icon/out.png"),
Util.LoadEmbeddedSprite("assets/icon/in.png")
];
private enum EStationTipLayout
{
None,
@@ -1392,6 +1411,7 @@ public static class LogisticsPatch
var itemCount = storage.count;
var itemLimit = _layout == EStationTipLayout.InterstellarLogistics ? _remoteStorageMaxTotal : _localStorageMaxTotal;
var barPositionChanged = false;
if (storageState.ItemCount != itemCount)
{
storageState.ItemCount = itemCount;
@@ -1411,8 +1431,13 @@ public static class LogisticsPatch
);
_sliderCurrent[i].gameObject.SetActive(true);
}
barPositionChanged = true;
}
}
else
{
if (itemCount > itemLimit) itemCount = itemLimit;
}
if (barEnabled)
{
@@ -1420,6 +1445,10 @@ public static class LogisticsPatch
if (storageState.ItemOrdered != itemOrdered)
{
storageState.ItemOrdered = itemOrdered;
barPositionChanged = true;
}
if (barPositionChanged)
{
switch (itemOrdered)
{
case > 0:
@@ -1434,7 +1463,6 @@ public static class LogisticsPatch
_pixelPerItem * itemOrdered + 0.49f,
StorageSliderHeight
);
_sliderOrdered[i].gameObject.SetActive(true);
break;
case < 0:
if (itemOrdered + itemCount < 0) itemOrdered = -itemCount;
@@ -1459,6 +1487,7 @@ public static class LogisticsPatch
{
storageState.ItemMax = itemMax;
_sliderBg[i].gameObject.SetActive(itemMax > 0);
if (itemMax > itemLimit) itemMax = itemLimit;
((RectTransform)_sliderMax[i].transform).sizeDelta = new Vector2(
_pixelPerItem * itemMax,
StorageSliderHeight

View File

@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Collections.Generic;
using System.Reflection.Emit;
using HarmonyLib;
using UnityEngine;
@@ -41,29 +38,6 @@ public class PersistPatch : PatchImpl<PersistPatch>
return matcher.InstructionEnumeration();
}
// Patch to fix the issue that warning popup on VeinUtil upgraded to level 8000+
[HarmonyTranspiler]
[HarmonyPatch(typeof(ABN_VeinsUtil), nameof(ABN_VeinsUtil.CheckValue))]
private static IEnumerable<CodeInstruction> ABN_VeinsUtil_CheckValue_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldelem_R8),
new CodeMatch(OpCodes.Conv_R4),
new CodeMatch(OpCodes.Add),
new CodeMatch(OpCodes.Stloc_1)
);
// loc1 = Mathf.Round(n * 1000f) / 1000f;
matcher.Advance(3).Insert(
new CodeInstruction(OpCodes.Ldc_R4, 1000f),
new CodeInstruction(OpCodes.Mul),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Mathf), nameof(Mathf.Round))),
new CodeInstruction(OpCodes.Ldc_R4, 1000f),
new CodeInstruction(OpCodes.Div)
);
return matcher.InstructionEnumeration();
}
// Bring popup tip window to top layer
[HarmonyTranspiler]
[HarmonyPatch(typeof(UIButton), nameof(UIButton.LateUpdate))]

View File

@@ -5,7 +5,7 @@ using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine.UI;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UXAssist.Patches;
@@ -46,11 +46,11 @@ public static class TechPatch
if (enable)
{
TryPatchProto(true);
GameLogic.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
GameLogicProc.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
}
else
{
GameLogic.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
GameLogicProc.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
TryPatchProto(false);
}
}
@@ -189,11 +189,11 @@ public static class TechPatch
{
if (DSPGame.GameDesc != null)
TryPatchProto(DSPGame.GameDesc.isPeaceMode);
GameLogic.OnGameBegin += OnGameBegin;
GameLogicProc.OnGameBegin += OnGameBegin;
}
else
{
GameLogic.OnGameBegin -= OnGameBegin;
GameLogicProc.OnGameBegin -= OnGameBegin;
TryPatchProto(false);
}
}

View File

@@ -1,15 +1,331 @@
namespace UXAssist.Patches;
using Common;
using System.Linq;
using HarmonyLib;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using BepInEx.Configuration;
using Common;
using GameLogicProc = Common.GameLogic;
[PatchGuid(PluginInfo.PLUGIN_GUID)]
public class UIPatch : PatchImpl<UIPatch>
{
public static ConfigEntry<bool> PlanetVeinUtilizationEnabled;
public static void Init()
{
PlanetVeinUtilizationEnabled.SettingChanged += (_, _) => PlanetVeinUtilization.Enable(PlanetVeinUtilizationEnabled.Value);
}
public static void Start()
{
GameLogicProc.OnGameBegin += PlanetVeinUtilization.OnGameBegin;
Enable(true);
Functions.UIFunctions.InitMenuButtons();
PlanetVeinUtilization.Enable(PlanetVeinUtilizationEnabled.Value);
}
public static void Uninit()
{
PlanetVeinUtilization.Enable(false);
Enable(false);
GameLogicProc.OnGameBegin -= PlanetVeinUtilization.OnGameBegin;
}
private class PlanetVeinUtilization : PatchImpl<PlanetVeinUtilization>
{
private static VeinTypeInfo[] planetVeinCount = null;
private static VeinTypeInfo[] starVeinCount = null;
private static readonly Dictionary<int, bool> tmpGroups = [];
public static void OnGameBegin()
{
if (planetVeinCount != null)
{
foreach (VeinTypeInfo vti in planetVeinCount)
{
if (vti.textCtrl != null)
{
Object.Destroy(vti.textCtrl.gameObject);
}
}
planetVeinCount = null;
}
if (starVeinCount != null)
{
foreach (VeinTypeInfo vti in starVeinCount)
{
if (vti.textCtrl != null)
{
Object.Destroy(vti.textCtrl.gameObject);
}
}
starVeinCount = null;
}
var maxVeinId = LDB.veins.dataArray.Max(vein => vein.ID);
planetVeinCount = new VeinTypeInfo[maxVeinId + 1];
starVeinCount = new VeinTypeInfo[maxVeinId + 1];
InitializeVeinCountArray(planetVeinCount);
InitializeVeinCountArray(starVeinCount);
}
protected override void OnEnable()
{
if (planetVeinCount != null)
{
foreach (VeinTypeInfo vti in planetVeinCount)
{
vti.Reset();
vti.textCtrl?.gameObject.SetActive(true);
}
UIPlanetDetail_RefreshDynamicProperties_Postfix(UIRoot.instance.uiGame.planetDetail);
}
if (starVeinCount != null)
{
foreach (VeinTypeInfo vti in starVeinCount)
{
vti.Reset();
vti.textCtrl?.gameObject.SetActive(true);
}
UIStarDetail_RefreshDynamicProperties_Postfix(UIRoot.instance.uiGame.starDetail);
}
}
private static Vector2 GetAdjustedSizeDelta(Vector2 origSizeDelta)
{
return new Vector2(origSizeDelta.x + 40f, origSizeDelta.y);
}
protected override void OnDisable()
{
if (planetVeinCount != null)
{
foreach (VeinTypeInfo vti in planetVeinCount)
{
vti.Reset();
vti.textCtrl?.gameObject.SetActive(false);
}
}
if (starVeinCount != null)
{
foreach (VeinTypeInfo vti in starVeinCount)
{
vti.Reset();
vti.textCtrl?.gameObject.SetActive(false);
}
}
}
#region Helper functions
private static void ProcessVeinData(VeinTypeInfo[] veinCount, VeinData[] veinPool)
{
lock (veinPool)
{
foreach (VeinData veinData in veinPool)
{
if (veinData.groupIndex == 0 || veinData.amount == 0) continue;
if (tmpGroups.TryGetValue(veinData.groupIndex, out bool hasMiner))
{
if (hasMiner) continue;
hasMiner = veinData.minerCount > 0;
if (!hasMiner) continue;
tmpGroups[veinData.groupIndex] = true;
VeinTypeInfo vti = veinCount[(int)veinData.type];
vti.numVeinGroupsWithCollector++;
}
else
{
hasMiner = veinData.minerCount > 0;
tmpGroups.Add(veinData.groupIndex, hasMiner);
VeinTypeInfo vti = veinCount[(int)veinData.type];
vti.numVeinGroups++;
if (hasMiner)
{
vti.numVeinGroupsWithCollector++;
}
}
}
}
tmpGroups.Clear();
}
private static void FormatResource(int refId, UIResAmountEntry uiresAmountEntry, VeinTypeInfo vt)
{
if (vt.textCtrl == null)
{
var parent = uiresAmountEntry.labelText.transform.parent;
vt.textCtrl = Object.Instantiate(uiresAmountEntry.valueText, parent);
vt.textCtrl.font = uiresAmountEntry.labelText.font;
RectTransform trans = vt.textCtrl.rectTransform;
var pos = uiresAmountEntry.rectTrans.localPosition;
pos.x = pos.x + uiresAmountEntry.iconImage.rectTransform.localPosition.x - 25f;
trans.localPosition = pos;
Vector2 size = trans.sizeDelta;
size.x = 40f;
trans.sizeDelta = size;
}
else
{
RectTransform trans = vt.textCtrl.rectTransform;
Vector3 pos = trans.localPosition;
pos.y = uiresAmountEntry.rectTrans.localPosition.y;
trans.localPosition = pos;
}
vt.textCtrl.text = $"{vt.numVeinGroupsWithCollector}/{vt.numVeinGroups}";
}
private static void InitializeVeinCountArray(VeinTypeInfo[] veinCountArray)
{
for (int i = 0; i < veinCountArray.Length; i++)
{
veinCountArray[i] = new VeinTypeInfo();
}
}
#endregion
#region UIPlanetDetail patches
[HarmonyPrefix, HarmonyPatch(typeof(UIPlanetDetail), nameof(UIPlanetDetail.OnPlanetDataSet))]
public static void UIPlanetDetail_OnPlanetDataSet_Prefix(UIPlanetDetail __instance)
{
foreach (VeinTypeInfo vti in planetVeinCount)
{
vti.Reset();
}
}
[HarmonyPostfix, HarmonyPatch(typeof(UIPlanetDetail), nameof(UIPlanetDetail.RefreshDynamicProperties))]
public static void UIPlanetDetail_RefreshDynamicProperties_Postfix(UIPlanetDetail __instance)
{
PlanetData planet = __instance.planet;
if (planet == null || planet.runtimeVeinGroups == null || __instance.tabIndex != 0) { return; }
int observeLevelCheck = __instance.planet == GameMain.localPlanet ? 1 : 2;
if (GameMain.history.universeObserveLevel < observeLevelCheck) { return; }
foreach (VeinTypeInfo vti in planetVeinCount)
{
vti.numVeinGroups = 0;
vti.numVeinGroupsWithCollector = 0;
}
// count up the total number of vein groups per resource type, as well as the total number of groups that have a miner attached
PlanetFactory factory = planet.factory;
if (factory != null)
{
ProcessVeinData(planetVeinCount, factory.veinPool);
}
else
{
VeinGroup[] veinGroups = planet.runtimeVeinGroups;
lock (planet.veinGroupsLock)
{
for (int i = 1; i < veinGroups.Length; i++)
{
planetVeinCount[(int)veinGroups[i].type].numVeinGroups++;
}
}
}
// update each resource to show the following vein group info:
// Iron: <number of vein groups with miners> / <total number of vein groups>
foreach (UIResAmountEntry uiresAmountEntry in __instance.entries)
{
int refId = uiresAmountEntry.refId;
if (refId > 0 && refId < (int)EVeinType.Max)
{
var vt = planetVeinCount[refId];
if (vt.numVeinGroups > 0)
{
FormatResource(refId, uiresAmountEntry, vt);
}
else if (vt.textCtrl != null)
{
vt.textCtrl.text = "";
}
}
}
}
#endregion
#region UIStarDetail patches
[HarmonyPrefix, HarmonyPatch(typeof(UIStarDetail), nameof(UIStarDetail.OnStarDataSet))]
public static void UIStaretail_OnStarDataSet_Prefix(UIStarDetail __instance)
{
foreach (VeinTypeInfo vti in starVeinCount)
{
vti.Reset();
}
}
[HarmonyPostfix, HarmonyPatch(typeof(UIStarDetail), nameof(UIStarDetail.RefreshDynamicProperties))]
public static void UIStarDetail_RefreshDynamicProperties_Postfix(UIStarDetail __instance)
{
if (__instance.star == null || __instance.tabIndex != 0) { return; }
if (GameMain.history.universeObserveLevel < 2) { return; }
foreach (VeinTypeInfo vti in starVeinCount)
{
vti.numVeinGroups = 0;
vti.numVeinGroupsWithCollector = 0;
}
foreach (PlanetData planet in __instance.star.planets)
{
if (planet.runtimeVeinGroups == null) { continue; }
PlanetFactory factory = planet.factory;
if (factory != null)
{
ProcessVeinData(starVeinCount, factory.veinPool);
}
else
{
VeinGroup[] veinGroups = planet.runtimeVeinGroups;
lock (planet.veinGroupsLock)
{
for (int i = 1; i < veinGroups.Length; i++)
{
starVeinCount[(int)veinGroups[i].type].numVeinGroups++;
}
}
}
}
// update each resource to show the following vein group info:
// Iron: <number of vein groups with miners> / <total number of vein groups>
foreach (UIResAmountEntry uiresAmountEntry in __instance.entries)
{
int refId = uiresAmountEntry.refId;
if (refId > 0 && refId < (int)EVeinType.Max)
{
var vt = starVeinCount[refId];
if (vt.numVeinGroups > 0)
{
FormatResource(refId, uiresAmountEntry, vt);
}
else if (vt.textCtrl != null)
{
vt.textCtrl.text = "";
}
}
}
}
#endregion
}
public class VeinTypeInfo
{
public int numVeinGroups;
public int numVeinGroupsWithCollector;
public Text textCtrl;
public void Reset()
{
numVeinGroups = 0;
numVeinGroupsWithCollector = 0;
if (textCtrl != null)
{
textCtrl.text = "";
}
}
}
// Add config button to main menu

View File

@@ -22,8 +22,6 @@
* Enable game window resize
* Remember window position and size on last exit
* Convert Peace-Mode saves to Combat-Mode on loading
* Scale up mouse cursor
* Note: This will enable software cursor mode, which may cause mouse movement lag on heavy load.
* Mod manager profile based save folder
* Save files are stored in `Save\<ProfileName>` folder.
* Will use original save location if matching default profile name.
@@ -38,12 +36,8 @@
* When set game speed in mod `Auxilaryfunction`, this feature will be disabled.
* When mod `BulletTime` is installed, this feature will be hidden, but patch `BulletTime`'s speed control, to make its maximum speed 10x.
* Set process priority
* Set enabled CPU threads
* Increase maximum count of Metadata Instantiations to 20000 (from 2000)
* Increase capacity of player order queue to 128 (from 16)
* Starmap view:
* Add a star name filter, you can filter displayed star names by ores or planet types now.
* Add a dropdown box to show all stars' distance and/or planet count.
* Factory
* Sunlight at night
* Remove some build conditions
@@ -112,9 +106,6 @@
* Enable player actions in globe view
* Hide tips for soil piles changes
* Enhanced count control for hand-make
* Shortcut keys for showing stars' name
* Add a shortcut key to always show all star names in starmap when holding, default is `Alt`
* Add a shortcut key to toggle between three star name display states in starmap: `Original state`, `Show all names`, `Hide all names`, default is `Tab`, will restore to original state when closing starmap
* Auto navigation on sailings
* It keeps Icarus on course to the target planet
* It will try to bypass any obstacles(planets, stars or dark-fog hives) on the way
@@ -136,6 +127,14 @@
* This enables batch buying out techs with their prerequisites. Buy-out button is shown for all locked techs/upgrads.
* Combat
* Open Dark Fog Communicator anywhere
* UI
* Embedded [Planet Vein Untilization](https://thunderstore.io/c/dyson-sphere-program/p/testpushpleaseignore/Planet_Vein_Utilization/) due to its lack of maintainance, with minor bug fixes.
* Shortcut keys for showing stars' name
* Add a shortcut key to always show all star names in starmap when holding, default is `Alt`
* Add a shortcut key to toggle between three star name display states in starmap: `Original state`, `Show all names`, `Hide all names`, default is `Tab`, will restore to original state when closing starmap
* Starmap view:
* Add a star name filter, you can filter displayed star names by ores or planet types now.
* Add a dropdown box to show all stars' distance and/or planet count.
## Notes
@@ -150,6 +149,7 @@
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI implementations
* [OffGridConstruction](https://github.com/Velociraptor115-DSPModding/OffGridConstruction): Off-grid building & stepped rotation implementations
* [CruiseAssist](https://dsp.thunderstore.io/package/tanu/CruiseAssist/) and its extension [AutoPilot](https://dsp.thunderstore.io/package/tanu/AutoPilot/): `Auto navigation on sailings` and `Auto-cruise` implementations
* [Planet Vein Untilization](https://thunderstore.io/c/dyson-sphere-program/p/testpushpleaseignore/Planet_Vein_Utilization/)
</details>
@@ -179,8 +179,6 @@
* 可调整游戏窗口大小(可最大化和拖动边框)
* 记住上次退出时的窗口位置和大小
* 在加载和平模式存档时将其转换为战斗模式
* 放大鼠标指针
* 注意这将启用软件指针模式可能会在CPU负载较重时导致鼠标移动延迟
* 基于mod管理器配置档案名的存档文件夹
* 存档文件会存储在`Save\<ProfileName>`文件夹中
* 如果匹配默认配置档案名则使用原始存档位置
@@ -195,12 +193,8 @@
* 当在`Auxilaryfunction`mod中设置游戏速度时此功能将被禁用
* 当安装了`BulletTime`mod时此功能将被隐藏但会对`BulletTime`的速度控制打补丁使其最大速度变为10倍
* 设置进程优先级
* 设置使用的CPU线程
* 将元数据提取的最大数量增加到20000(原来为2000)
* 将玩家指令队列的容量增加到128(原来为16)
* 星图:
* 添加星系名过滤器,现在可以按矿物或行星类型过滤显示的星系名
* 添加了一个下拉框用以切换显示所有星系的距离和/或行星数量
* 工厂
* 夜间日光灯
* 移除部分不影响游戏逻辑的建造条件
@@ -270,9 +264,6 @@
* 在行星视图中允许玩家操作
* 隐藏沙土数量变动的提示
* 手动制造物品的数量控制改进
* 启用显示所有星系名称的快捷键
* 新增一个快捷键,按住后始终在星图显示所有星系名称,默认为`Alt`
* 新增一个快捷键,在星图视图切换三种星系名称显示状态:`原始显示状态``显示所有名称``隐藏所有名称`,默认为`Tab`,关闭星图时会恢复到原始状态
* 航行时自动导航
* 它会保持伊卡洛斯飞向目标星球
* 它会尝试绕过途中的任何障碍物(行星、恒星或黑雾巢穴)
@@ -294,6 +285,14 @@
* 这使得可以批量买断科技及其所有前置科技。所有未解锁的科技/升级都会显示买断按钮。
* 战斗
* 在任意位置打开黑雾通讯器
* UI
* 启用显示所有星系名称的快捷键
* 新增一个快捷键,按住后始终在星图显示所有星系名称,默认为`Alt`
* 新增一个快捷键,在星图视图切换三种星系名称显示状态:`原始显示状态``显示所有名称``隐藏所有名称`,默认为`Tab`,关闭星图时会恢复到原始状态
* 星图:
* 添加星系名过滤器,现在可以按矿物或行星类型过滤显示的星系名
* 添加了一个下拉框用以切换显示所有星系的距离和/或行星数量
* 由于缺乏维护,整合内置了[Planet Vein Untilization](https://thunderstore.io/c/dyson-sphere-program/p/testpushpleaseignore/Planet_Vein_Utilization/),并修复了一些小错误。
## 注意事项
@@ -308,5 +307,6 @@
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI实现
* [OffGridConstruction](https://github.com/Velociraptor115-DSPModding/OffGridConstruction): 脱离网格建造以及小角度旋转的实现
* [CruiseAssist](https://dsp.thunderstore.io/package/tanu/CruiseAssist/)及其扩展[AutoPilot](https://dsp.thunderstore.io/package/tanu/AutoPilot/): `航行时自动导航``自动巡航`的实现
* [Planet Vein Untilization](https://thunderstore.io/c/dyson-sphere-program/p/testpushpleaseignore/Planet_Vein_Utilization/)
</details>

View File

@@ -613,7 +613,7 @@ public abstract class MyWindowManager
/*
//_Create -> _Init
[HarmonyPostfix, HarmonyPatch(typeof(UIGame), "_OnCreate")]
[HarmonyPostfix, HarmonyPatch(typeof(UIGame), nameof(UIGame._OnCreate))]
public static void UIGame__OnCreate_Postfix()
{
}
@@ -638,7 +638,7 @@ public abstract class MyWindowManager
}
/*
[HarmonyPostfix, HarmonyPatch(typeof(UIGame), "_OnFree")]
[HarmonyPostfix, HarmonyPatch(typeof(UIGame), nameof(UIGame._OnFree))]
public static void UIGame__OnFree_Postfix()
{
foreach (var win in Windows)

View File

@@ -24,10 +24,9 @@ public static class UIConfigWindow
I18N.Add("Logistics", "Logistics", "物流");
I18N.Add("Player/Mecha", "Player/Mecha", "玩家/机甲");
I18N.Add("Dyson Sphere", "Dyson Sphere", "戴森球");
I18N.Add("Tech/Combat", "Tech/Combat", "科研/战斗");
I18N.Add("Tech/Combat/UI", "Tech/Combat/UI", "科研/战斗/UI");
I18N.Add("Enable game window resize", "Enable game window resize (maximum box and thick frame)", "可调整游戏窗口大小(可最大化和拖动边框)");
I18N.Add("Remeber window position and size on last exit", "Remeber window position and size on last exit", "记住上次退出时的窗口位置和大小");
I18N.Add("Scale up mouse cursor", "Scale up mouse cursor", "放大鼠标指针");
/*
I18N.Add("Better auto-save mechanism", "Better auto-save mechanism", "更好的自动存档机制");
I18N.Add("Better auto-save mechanism tips", "Auto saves are stored in 'Save\\AutoSaves' folder, filenames are combined with cluster address and date-time", "自动存档会以星区地址和日期时间组合为文件名存储在'Save\\AutoSaves'文件夹中");
@@ -48,14 +47,6 @@ public static class UIConfigWindow
I18N.Add("Normal", "Normal", "正常");
I18N.Add("Below Normal", "Below Normal", "低于正常");
I18N.Add("Idle", "Idle", "空闲");
I18N.Add("Enabled CPUs", "Enabled CPU Threads", "使用CPU线程");
I18N.Add("All CPUs", "All CPUs", "所有CPU");
I18N.Add("First {0} CPUs", "First {0} CPUs", "前{0}个CPU");
I18N.Add("First 8 CPUs", "First 8 CPUs", "前8个CPU");
I18N.Add("First CPU only", "First CPU only", "仅第一个CPU");
I18N.Add("All P-Cores", "All P-Cores", "所有性能(P)核心");
I18N.Add("All E-Cores", "All E-Cores", "所有能效(E)核心");
I18N.Add("CPU Info", "CPU Info", "CPU信息");
I18N.Add("Unlimited interactive range", "Unlimited interactive range", "无限交互距离");
I18N.Add("Night Light", "Sunlight at night", "夜间日光灯");
I18N.Add("Angle X:", "Angle X:", "入射角度X:");
@@ -153,6 +144,7 @@ public static class UIConfigWindow
I18N.Add("Set \"Sorter Cargo Stacking\" to unresearched state", "Set \"Sorter Cargo Stacking\" to unresearched state", "将\"分拣器货物叠加\"设为未研究状态");
I18N.Add("Unlock all techs with metadata", "Unlock all techs with metadata", "使用元数据解锁所有科技");
I18N.Add("Open Dark Fog Communicator", "Open Dark Fog Communicator", "打开黑雾通讯器");
I18N.Add("Planet vein utilization", "Planet vein utilization in star map", "宇宙视图行星/星系矿脉数量显示");
I18N.Apply();
MyConfigWindow.OnUICreated += CreateUI;
MyConfigWindow.OnUpdateUI += UpdateUI;
@@ -293,6 +285,7 @@ public static class UIConfigWindow
private static void CreateUI(MyConfigWindow wnd, RectTransform trans)
{
UnityEngine.UI.Text txt;
_windowTrans = trans;
wnd.AddTabGroup(trans, "UXAssist", "tab-group-uxassist");
var tab1 = wnd.AddTab(trans, "General");
@@ -301,9 +294,6 @@ public static class UIConfigWindow
wnd.AddCheckBox(x, y, tab1, GamePatch.EnableWindowResizeEnabled, "Enable game window resize");
y += 36f;
wnd.AddCheckBox(x, y, tab1, GamePatch.LoadLastWindowRectEnabled, "Remeber window position and size on last exit");
y += 36f;
var txt = wnd.AddText2(x + 2f, y, tab1, "Scale up mouse cursor", 15, "text-scale-up-mouse-cursor");
wnd.AddSlider(x + txt.preferredWidth + 7f, y + 6f, tab1, GamePatch.MouseCursorScaleUpMultiplier, [1, 2, 3, 4], "0x", 100f);
/*
y += 30f;
wnd.AddCheckBox(x, y, tab1, GamePatch.AutoSaveOptEnabled, "Better auto-save mechanism");
@@ -341,25 +331,6 @@ public static class UIConfigWindow
}
y += 36f;
wnd.AddComboBox(x + 2f, y, tab1, "Process priority").WithItems("High", "Above Normal", "Normal", "Below Normal", "Idle").WithSize(100f, 0f).WithConfigEntry(WindowFunctions.ProcessPriority);
var details = WindowFunctions.ProcessorDetails;
string[] affinities;
if (details.HybridArchitecture)
{
affinities = new string[5];
affinities[3] = "All P-Cores";
affinities[4] = "All E-Cores";
}
else
{
affinities = new string[3];
}
affinities[0] = "All CPUs";
affinities[1] = string.Format("First {0} CPUs".Translate(), details.ThreadCount / 2);
affinities[2] = details.ThreadCount > 16 ? "First 8 CPUs" : "First CPU only";
y += 36f;
wnd.AddComboBox(x + 2f, y, tab1, "Enabled CPUs").WithItems(affinities).WithSize(200f, 0f).WithConfigEntry(WindowFunctions.ProcessAffinity);
y += 36f;
((RectTransform)wnd.AddButton(x, y, tab1, "CPU Info", 16, "button-show-cpu-info", WindowFunctions.ShowCPUInfo).transform).sizeDelta = new Vector2(100f, 25f);
var tab2 = wnd.AddTab(trans, "Factory");
x = 0f;
@@ -754,9 +725,12 @@ public static class UIConfigWindow
wnd.AddSlider(x + txt.preferredWidth + 5f, y + 6f, tab5, DysonSpherePatch.AutoConstructMultiplier, [1, 2, 5, 10, 20, 50, 100], "0", 100f);
_dysonTab = tab5;
var tab6 = wnd.AddTab(trans, "Tech/Combat");
var tab6 = wnd.AddTab(trans, "Tech/Combat/UI");
x = 10;
y = 10;
wnd.AddCheckBox(x, y, tab6, UIPatch.PlanetVeinUtilizationEnabled, "Planet vein utilization");
y += 36f;
y += 36f;
wnd.AddCheckBox(x, y, tab6, TechPatch.BatchBuyoutTechEnabled, "Buy out techs with their prerequisites");
y += 36f;
wnd.AddCheckBox(x, y, tab6, TechPatch.SorterCargoStackingEnabled, "Restore upgrades of \"Sorter Cargo Stacking\" on panel");

View File

@@ -14,7 +14,7 @@ using UXAssist.Functions;
using UXAssist.Patches;
using UXAssist.UI;
using Util = UXAssist.Common.Util;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UXAssist;
@@ -22,6 +22,7 @@ namespace UXAssist;
[BepInDependency(DSPModSavePlugin.MODGUID)]
[CommonAPISubmoduleDependency(nameof(CustomKeyBindSystem))]
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
[BepInDependency(ModsCompat.PlanetVeinUtilization.PlanetVeinUtilizationGuid, BepInDependency.DependencyFlags.SoftDependency)]
public class UXAssist : BaseUnityPlugin, IModCanSave
{
public new static readonly ManualLogSource Logger =
@@ -29,6 +30,7 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
private static ConfigFile _dummyConfig;
private Type[] _patches, _compats;
private readonly Harmony _harmony = new(PluginInfo.PLUGIN_GUID);
#region IModCanSave
private const ushort ModSaveVersion = 1;
@@ -51,6 +53,11 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
}
#endregion
UXAssist()
{
ModsCompat.PlanetVeinUtilization.Run(_harmony);
}
private void Awake()
{
_dummyConfig = new ConfigFile(Path.Combine(Paths.ConfigPath, PluginInfo.PLUGIN_GUID + "_dummy.cfg"), false)
@@ -63,8 +70,6 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
"Load last window position and size when game starts");
GamePatch.LastWindowRect = Config.Bind("Game", "LastWindowRect", new Vector4(0f, 0f, 0f, 0f),
"Last window position and size");
GamePatch.MouseCursorScaleUpMultiplier = Config.Bind("Game", "MouseCursorScaleUpMultiplier", 1,
"Mouse cursor scale up multiplier");
GamePatch.ProfileBasedSaveFolderEnabled = Config.Bind("Game", "ProfileBasedSaveFolder", false,
"Profile-based save folder");
GamePatch.ProfileBasedOptionEnabled = Config.Bind("Game", "ProfileBasedOption", false,
@@ -81,12 +86,6 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
"Game UPS factor (1.0 for normal speed)");
WindowFunctions.ProcessPriority = Config.Bind("Game", "ProcessPriority", 2,
new ConfigDescription("Game process priority\n 0: High 1: Above Normal 2: Normal 3: Below Normal 4: Idle", new AcceptableValueRange<int>(0, 4)));
WindowFunctions.ProcessAffinity = Config.Bind("Game", "CPUAffinity", -1,
new ConfigDescription("""
Game process CPU affinity
0: All 1: First-half CPUs 2. First 8 CPUs (if total CPUs are greater than 16)
3. All Performance Cores(If Intel 13th or greater) 4. All Efficiency Cores(If Intel 13th or greater)
""", new AcceptableValueRange<int>(0, 4)));
FactoryPatch.UnlimitInteractiveEnabled = Config.Bind("Factory", "UnlimitInteractive", false,
"Unlimit interactive range");
@@ -203,12 +202,14 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
DysonSpherePatch.OnlyConstructNodesEnabled = Config.Bind("DysonSphere", "OnlyConstructNodes", false,
"Construct only nodes but frames");
DysonSpherePatch.AutoConstructMultiplier = Config.Bind("DysonSphere", "AutoConstructMultiplier", 1, "Dyson Sphere auto-construct speed multiplier");
UIPatch.PlanetVeinUtilizationEnabled = Config.Bind("UI", "PlanetVeinUtilization", false,
"Planet vein utilization");
I18N.Init();
I18N.Add("UXAssist Config", "UXAssist Config", "UX助手设置");
// UI Patches
GameLogic.Enable(true);
GameLogicProc.Enable(true);
UIConfigWindow.Init();
@@ -228,7 +229,7 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
_patches?.Do(type => type.GetMethod("Start")?.Invoke(null, null));
object[] parameters = [UIPatch.GetHarmony()];
object[] parameters = [_harmony];
_compats?.Do(type => type.GetMethod("Start")?.Invoke(null, parameters));
}
@@ -236,9 +237,8 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
{
_patches?.Do(type => type.GetMethod("Uninit")?.Invoke(null, null));
UIPatch.Enable(false);
MyWindowManager.Enable(false);
GameLogic.Enable(false);
GameLogicProc.Enable(false);
}
private void Update()
@@ -254,10 +254,7 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
GamePatch.OnInputUpdate();
FactoryPatch.OnInputUpdate();
PlayerPatch.OnInputUpdate();
}
private void FixedUpdate()
{
LogisticsPatch.OnUpdate();
}
}

View File

@@ -4,7 +4,7 @@
<TargetFramework>net472</TargetFramework>
<BepInExPluginGuid>org.soardev.uxassist</BepInExPluginGuid>
<Description>DSP MOD - UXAssist</Description>
<Version>1.3.6</Version>
<Version>1.4.3</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<PackageId>UXAssist</PackageId>
@@ -15,13 +15,12 @@
<ItemGroup>
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
<PackageReference Include="DysonSphereProgram.GameLibs" Version="0.10.32.*-r.*" />
<PackageReference Include="UnityEngine.Modules" Version="2022.3.53" IncludeAssets="compile" />
<!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="0.10.32.*-r.*" /> -->
<PackageReference Include="DysonSphereProgram.Modding.CommonAPI" Version="1.6.5" />
<PackageReference Include="DysonSphereProgram.Modding.DSPModSave" Version="1.*" />
</ItemGroup>
<!--
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath>
@@ -30,7 +29,6 @@
<HintPath>..\AssemblyFromGame\UnityEngine.UI.dll</HintPath>
</Reference>
</ItemGroup>
-->
<ItemGroup>
<EmbeddedResource Include="assets/signal/energy-fragment.png" />
@@ -63,7 +61,7 @@
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip&#xA;powershell Compress-Archive -Force -DestinationPath 'package/$(ProjectName)-$(Version).zip' -Path &quot;$(TargetPath)&quot;, package/icon.png, package/manifest.json, README.md, CHANGELOG.md" />
</Target>
</Project>

View File

@@ -1,6 +1,6 @@
{
"name": "UXAssist",
"version_number": "1.3.6",
"version_number": "1.4.3",
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/UXAssist",
"description": "Some functions and patches for better user experience / 一些提升用户体验的功能和补丁",
"dependencies": [

View File

@@ -1,8 +1,7 @@
using System.Collections.Generic;
using BepInEx.Configuration;
using HarmonyLib;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UniverseGenTweaks;
public static class BirthPlanetPatch
@@ -75,12 +74,12 @@ public static class BirthPlanetPatch
HighLuminosityBirthStar.SettingChanged += (_, _) => PatchBirthThemeData();
PatchBirthThemeData();
_patch ??= Harmony.CreateAndPatchAll(typeof(BirthPlanetPatch));
GameLogic.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
GameLogicProc.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
}
public static void Uninit()
{
GameLogic.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
GameLogicProc.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
_patch?.UnpatchSelf();
_patch = null;
}

View File

@@ -3,6 +3,8 @@
## Changelog
* 1.2.11
* Fix issues which cause universe settings not applied on staring a new game (again again).
* 1.2.10
* Fix issues which cause universe settings not applied on staring a new game or loading game (again).
* Reset star distance/flatten settings on entering galaxy creation screen.
@@ -46,6 +48,8 @@
## 更新日志
* 1.2.11
* (再次再次)修复新建游戏时宇宙设置没有应用的问题
* 1.2.10
* (再次)修复新建游戏或加载存档时宇宙设置没有应用的问题
* 进入宇宙创建界面时重置星系间距/扁平度设置

View File

@@ -153,7 +153,7 @@ public static class EpicDifficulty
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(GameDesc), "get_oilAmountMultiplier")]
[HarmonyPatch(typeof(GameDesc), nameof(GameDesc.oilAmountMultiplier), MethodType.Getter)]
private static IEnumerable<CodeInstruction> GameDesc_get_oilAmountMultiplier_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);

View File

@@ -99,17 +99,14 @@ public class MoreSettings
_minDistSlider.maxValue = 50f;
_minDistSlider.value = (float)(_minDist * 10.0);
_minStepTitle.name = "min-step";
_minStepSlider.minValue = (float)(_minDist * 10.0);
_minStepSlider.maxValue = (float)(_maxStep * 10.0);
_minStepSlider.value = (float)(_minStep * 10.0);
_maxStepTitle.name = "max-step";
_maxStepSlider.minValue = (float)(_minStep * 10.0);
_maxStepSlider.maxValue = 100f;
_maxStepSlider.value = (float)(_maxStep * 10.0);
_flattenTitle.name = "flatten";
_flattenSlider.minValue = 1f;
_flattenSlider.maxValue = 50f;
_flattenSlider.value = (float)(_flatten * 50.0);
@@ -118,6 +115,8 @@ public class MoreSettings
_minStepText.text = _minStep.ToString();
_maxStepText.text = _maxStep.ToString();
_flattenText.text = _flatten.ToString();
UniverseGenTweaks.Logger.LogDebug($"Updated slider controls: {_minStepSlider.minValue}, {_minStepSlider.maxValue}, {_maxStepSlider.minValue}, {_maxStepSlider.maxValue}");
}
[HarmonyPostfix]
@@ -136,24 +135,9 @@ public class MoreSettings
flattenLocalizer.stringKey = "扁平度";
_minDistTitle.name = "min-dist";
_minDistSlider.minValue = 10f;
_minDistSlider.maxValue = 50f;
_minDistSlider.value = (float)(_minDist * 10.0);
_minStepTitle.name = "min-step";
_minStepSlider.minValue = (float)(_minDist * 10.0);
_minStepSlider.maxValue = (float)(_maxStep * 10.0);
_minStepSlider.value = (float)(_minStep * 10.0);
_maxStepTitle.name = "max-step";
_maxStepSlider.minValue = (float)(_minStep * 10.0);
_maxStepSlider.maxValue = 100f;
_maxStepSlider.value = (float)(_maxStep * 10.0);
_flattenTitle.name = "flatten";
_flattenSlider.minValue = 1f;
_flattenSlider.maxValue = 50f;
_flattenSlider.value = (float)(_flatten * 50.0);
TransformDeltaY(_minDistTitle.transform, -36f);
TransformDeltaY(_minStepTitle.transform, -36f * 2);
@@ -164,25 +148,36 @@ public class MoreSettings
TransformDeltaY(__instance.sandboxToggle.transform.parent, -36f * 4);
TransformDeltaY(__instance.propertyMultiplierText.transform, -36f * 4);
TransformDeltaY(__instance.addrText.transform.parent, -36f * 4);
RemoveAllListeners();
UpdateSliderControls();
AddListeners(__instance);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(UIGalaxySelect), nameof(UIGalaxySelect._OnOpen))]
private static void UIGalaxySelect__OnOpen_Prefix()
private static void UIGalaxySelect__OnOpen_Prefix(UIGalaxySelect __instance)
{
_minDist = DEFAULT_MIN_DIST;
_minStep = DEFAULT_MIN_STEP;
_maxStep = DEFAULT_MAX_STEP;
_flatten = DEFAULT_FLATTEN;
RemoveAllListeners();
UpdateSliderControls();
AddListeners(__instance);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(UIGalaxySelect), nameof(UIGalaxySelect._OnRegEvent))]
private static void UIGalaxySelect__OnRegEvent_Postfix(UIGalaxySelect __instance)
private static void RemoveAllListeners()
{
_minDistSlider.onValueChanged.RemoveAllListeners();
_minStepSlider.onValueChanged.RemoveAllListeners();
_maxStepSlider.onValueChanged.RemoveAllListeners();
_flattenSlider.onValueChanged.RemoveAllListeners();
}
private static void AddListeners(UIGalaxySelect uiGalaxySelect)
{
_minDistSlider.onValueChanged.AddListener(val =>
{
var newVal = Mathf.Round(val) / 10.0;
@@ -202,9 +197,8 @@ public class MoreSettings
}
}
_minStepSlider.minValue = (float)(_minDist * 10.0);
__instance.SetStarmapGalaxy();
uiGalaxySelect.SetStarmapGalaxy();
});
_minStepSlider.onValueChanged.RemoveAllListeners();
_minStepSlider.onValueChanged.AddListener(val =>
{
var newVal = Mathf.Round(val) / 10.0;
@@ -212,9 +206,8 @@ public class MoreSettings
_minStep = newVal;
_maxStepSlider.minValue = (float)(newVal * 10.0);
_minStepText.text = _minStep.ToString();
__instance.SetStarmapGalaxy();
uiGalaxySelect.SetStarmapGalaxy();
});
_maxStepSlider.onValueChanged.RemoveAllListeners();
_maxStepSlider.onValueChanged.AddListener(val =>
{
var newVal = Mathf.Round(val) / 10.0;
@@ -222,16 +215,15 @@ public class MoreSettings
_maxStep = newVal;
_minStepSlider.maxValue = (float)(newVal * 10.0);
_maxStepText.text = _maxStep.ToString();
__instance.SetStarmapGalaxy();
uiGalaxySelect.SetStarmapGalaxy();
});
_flattenSlider.onValueChanged.RemoveAllListeners();
_flattenSlider.onValueChanged.AddListener(val =>
{
var newVal = Mathf.Round(val) / 50.0;
if (newVal.Equals(_flatten)) return;
_flatten = newVal;
_flattenText.text = _flatten.ToString();
__instance.SetStarmapGalaxy();
uiGalaxySelect.SetStarmapGalaxy();
});
}
@@ -266,26 +258,21 @@ public class MoreSettings
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Start))]
private static void GameMain_Start_Prefix()
{
_gameMinDist = DEFAULT_MIN_DIST;
_gameMinStep = DEFAULT_MIN_STEP;
_gameMaxStep = DEFAULT_MAX_STEP;
_gameFlatten = DEFAULT_FLATTEN;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(GameData), nameof(GameData.NewGame))]
private static void GameData_NewGame_Prefix()
{
if (!Enabled.Value) return;
_gameMinDist = _minDist;
_gameMinStep = _minStep;
_gameMaxStep = _maxStep;
_gameFlatten = _flatten;
_minDist = DEFAULT_MIN_DIST;
_minStep = DEFAULT_MIN_STEP;
_maxStep = DEFAULT_MAX_STEP;
_flatten = DEFAULT_FLATTEN;
if (DSPGame.GameDesc != null)
{
if (GameMain.data != null) return;
_gameMinDist = _minDist;
_gameMinStep = _minStep;
_gameMaxStep = _maxStep;
_gameFlatten = _flatten;
}
else
{
_gameMinDist = DEFAULT_MIN_DIST;
_gameMinStep = DEFAULT_MIN_STEP;
_gameMaxStep = DEFAULT_MAX_STEP;
_gameFlatten = DEFAULT_FLATTEN;
}
}
[HarmonyTranspiler]

View File

@@ -6,7 +6,7 @@
<AssemblyName>UniverseGenTweaks</AssemblyName>
<BepInExPluginGuid>org.soardev.universegentweaks</BepInExPluginGuid>
<Description>DSP MOD - UniverseGenTweaks</Description>
<Version>1.2.10</Version>
<Version>1.2.11</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
@@ -15,8 +15,8 @@
<ItemGroup>
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
<PackageReference Include="DysonSphereProgram.GameLibs" Version="0.10.32.*-r.*" />
<PackageReference Include="UnityEngine.Modules" Version="2022.3.53" IncludeAssets="compile" />
<!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="0.10.32.*-r.*" /> -->
<PackageReference Include="DysonSphereProgram.Modding.DSPModSave" Version="1.*" />
</ItemGroup>
@@ -24,6 +24,15 @@
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>..\AssemblyFromGame\UnityEngine.UI.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UXAssist\UXAssist.csproj" />
</ItemGroup>

View File

@@ -1,6 +1,6 @@
{
"name": "UniverseGenTweaks",
"version_number": "1.2.10",
"version_number": "1.2.11",
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/UniverseGenTweaks",
"description": "Universe Generation Tweaks / 宇宙生成参数调节",
"dependencies": [