1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2026-06-19 16:41:10 +08:00

Compare commits

37 Commits

Author SHA1 Message Date
soarqin 09cdaf3a12 balance tweaks 2025-10-30 16:03:11 +08:00
soarqin 8d5bb140e1 fix crashes 2025-10-30 00:12:47 +08:00
soarqin c99c59a117 work in progress 2025-10-29 22:30:10 +08:00
soarqin 61811f9a8c crash fix 2025-10-29 21:51:52 +08:00
soarqin cf3117e0da minor opt 2025-10-29 21:38:53 +08:00
soarqin dfd34601cf update for new game update 2025-10-29 20:54:41 +08:00
soarqin 6934607fca WIP for logistic_hub 2025-10-29 20:45:21 +08:00
soarqin be9de43492 fix issue 2025-10-29 20:22:23 +08:00
soarqin 2dbf017a5e update LogisticMiner to be compatible with latest game update 2025-10-29 15:27:53 +08:00
soarqin 3c7744047c update Game dll 2025-10-29 15:27:23 +08:00
soarqin a9959a2f07 try to fix a strange issue 2025-10-29 15:27:13 +08:00
soarqin 77f5803a24 UniverseGenTweaks v1.2.11 2025-10-21 00:36:32 +08:00
soarqin e9bbcf5e2c bug fix 2025-10-20 22:45:29 +08:00
soarqin a183485286 UXAssist: some fixes 2025-10-04 17:23:41 +08:00
soarqin 5a6cfb18c9 UXAssist: Drag build Power Towers fix 2025-10-03 16:16:02 +08:00
soarqin 49226001be UXAssist v1.4.2 2025-09-30 13:02:39 +08:00
soarqin 7c1e88f86d UXAssist v1.4.1 2025-09-30 00:15:26 +08:00
soarqin 16429936a9 UXAssist v1.4.0 and CheatEnabler v2.4.0 2025-09-29 23:46:44 +08:00
soarqin d711dd25ef remove cpu affinity settings, as they are officially supported 2025-09-29 23:34:17 +08:00
soarqin e909b6d9d2 rename GameLogicProc back to make things compatible with old dependants 2025-09-29 23:34:17 +08:00
soarqin 2a4008deac fixed rest issues 2025-09-29 23:34:17 +08:00
soarqin 6b423225fe partial fix belt signal 2025-09-29 23:34:17 +08:00
soarqin 9d9a12c1af more fixes to make sure nothing working wrong on game 2025-09-29 23:34:17 +08:00
soarqin 1d11ba90bd we make them compile first 2025-09-29 23:34:17 +08:00
soarqin a5dc7c5825 Starmap view star name display: add star index 2025-09-29 17:02:10 +08:00
soarqin 73ebcf1aa3 more works 2025-09-28 17:36:19 +08:00
soarqin dc092d7f6f Planet Vein Utilization embedded 2025-09-28 00:42:16 +08:00
soarqin d9f87ca4e9 Logistics Panel Info fix again again 2025-09-24 15:06:09 +08:00
soarqin a3c60c32ca Logistics Panel Info fix again 2025-09-24 12:19:50 +08:00
soarqin 96a9e8a570 Logistics Panel Info fix 2025-09-24 02:51:41 +08:00
soarqin d6a8275938 minor fix 2025-09-21 23:01:29 +08:00
soarqin b995503f58 resolve dotnet format warning 2025-09-21 16:39:57 +08:00
soarqin a25f74443d donet format 2025-09-21 15:38:03 +08:00
soarqin 5f37b8b6d6 Fix a method use that missing in .NET Framework 4.5 2025-09-21 15:13:43 +08:00
soarqin 4584895345 new function to generate illegal shells quickly 2025-09-21 01:37:09 +08:00
soarqin 5b4633e54c ui button fixes 2025-09-21 01:36:54 +08:00
soarqin 31b1d90d5d work in progress 2025-09-19 22:18:48 +08:00
74 changed files with 2876 additions and 2116 deletions
Binary file not shown.
Binary file not shown.
+6
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
+4 -6
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>
+386 -78
View File
@@ -15,12 +15,70 @@ public static class DysonSphereFunctions
public static ConfigEntry<bool> IllegalDysonShellFunctionsEnabled;
public static ConfigEntry<int> ShellsCountForFunctions;
const ulong rawNum0 = 0x3FED4D1BA3920BFAUL; // cosr
const ulong rawNum1 = 0x3FD9B9832ADBFC16UL; // sinr
const ulong rawNum2 = 0x3FE279A74590331DUL;
const ulong rawNum3 = 0x3FEBB67AE8584CAAUL; // cos30
private static readonly double factor0 = RawToDouble(rawNum0);
private static readonly double factor1 = RawToDouble(rawNum1);
private static readonly double factor2 = RawToDouble(rawNum2);
private static readonly double factor3 = RawToDouble(rawNum3);
private static readonly PrecalculatedTriangle[] PrecalculatedTriangles = [
new PrecalculatedTriangle() { MaxOrbitRadius = 6869, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x45D66000U)}, PosB = new Vector3() { x = RawToFloat(0x2C88BEC4U), y = RawToFloat(0x00000000U), z = RawToFloat(0xC5D66000U)}, PosC = new Vector3() { x = RawToFloat(0xC5D66000U), y = RawToFloat(0x00000000U), z = RawToFloat(0xABB1589BU)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 13573, PosA = new Vector3() { x = RawToFloat(0x46540800U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2C87400AU)}, PosB = new Vector3() { x = RawToFloat(0x4652DEA6U), y = RawToFloat(0x00000000U), z = RawToFloat(0xC4B14E71U)}, PosC = new Vector3() { x = RawToFloat(0xC6540800U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAC2F683EU)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 21257, PosA = new Vector3() { x = RawToFloat(0x46A60400U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2CD3CBAAU)}, PosB = new Vector3() { x = RawToFloat(0xC6070C9DU), y = RawToFloat(0x00000000U), z = RawToFloat(0xC697A9AEU)}, PosC = new Vector3() { x = RawToFloat(0xC6A60400U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAC8956FFU)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 29718, PosA = new Vector3() { x = RawToFloat(0x469B4FBEU), y = RawToFloat(0x00000000U), z = RawToFloat(0x46AC7DAAU)}, PosB = new Vector3() { x = RawToFloat(0x46E81C00U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2D140EBCU)}, PosC = new Vector3() { x = RawToFloat(0xC6E81C00U), y = RawToFloat(0x00000000U), z = RawToFloat(0xACC0046AU)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 38834, PosA = new Vector3() { x = RawToFloat(0x4717AE00U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2D4181A3U)}, PosB = new Vector3() { x = RawToFloat(0x45FC49B0U), y = RawToFloat(0x00000000U), z = RawToFloat(0xC7145D79U)}, PosC = new Vector3() { x = RawToFloat(0xC717AE00U), y = RawToFloat(0x00000000U), z = RawToFloat(0xACFAF5D4U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 48523, PosA = new Vector3() { x = RawToFloat(0x473D8800U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2D71CBB9U)}, PosB = new Vector3() { x = RawToFloat(0xC73D8800U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAD1CCB2AU)}, PosC = new Vector3() { x = RawToFloat(0xC72D2539U), y = RawToFloat(0x00000000U), z = RawToFloat(0x469A2DB9U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 58724, PosA = new Vector3() { x = RawToFloat(0x47656000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2D925038U)}, PosB = new Vector3() { x = RawToFloat(0xC7656000U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAD3DC153U)}, PosC = new Vector3() { x = RawToFloat(0xC7518B63U), y = RawToFloat(0x00000000U), z = RawToFloat(0x46BA9727U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 69389, PosA = new Vector3() { x = RawToFloat(0x47878200U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2DACE001U)}, PosB = new Vector3() { x = RawToFloat(0xC7878200U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAD603407U)}, PosC = new Vector3() { x = RawToFloat(0xC7078200U), y = RawToFloat(0x00000000U), z = RawToFloat(0x476AB4D7U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 80481, PosA = new Vector3() { x = RawToFloat(0x479D3000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2DC88874U)}, PosB = new Vector3() { x = RawToFloat(0xC79D3000U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAD82095EU)}, PosC = new Vector3() { x = RawToFloat(0xC71D3000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x478820DDU)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 91970, PosA = new Vector3() { x = RawToFloat(0x47B2A01EU), y = RawToFloat(0x00000000U), z = RawToFloat(0x461631C0U)}, PosB = new Vector3() { x = RawToFloat(0x47B39C00U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2DE5234DU)}, PosC = new Vector3() { x = RawToFloat(0xC7B39C00U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAD9495E6U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 103831, PosA = new Vector3() { x = RawToFloat(0x476E65BEU), y = RawToFloat(0x00000000U), z = RawToFloat(0x47A4101EU)}, PosB = new Vector3() { x = RawToFloat(0x47CACB00U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2E015B75U)}, PosC = new Vector3() { x = RawToFloat(0xC7CACB00U), y = RawToFloat(0x00000000U), z = RawToFloat(0xADA7C3C0U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 116040, PosA = new Vector3() { x = RawToFloat(0x47E29F00U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2E108E84U)}, PosB = new Vector3() { x = RawToFloat(0xC7E29F00U), y = RawToFloat(0x00000000U), z = RawToFloat(0xADBB7A19U)}, PosC = new Vector3() { x = RawToFloat(0xC70C0F3EU), y = RawToFloat(0x00000000U), z = RawToFloat(0x47D7878CU)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 128580, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x47FB1D00U)}, PosB = new Vector3() { x = RawToFloat(0x47A80710U), y = RawToFloat(0x00000000U), z = RawToFloat(0x47BA9D10U)}, PosC = new Vector3() { x = RawToFloat(0x2EA02E04U), y = RawToFloat(0x00000000U), z = RawToFloat(0xC7FB1D00U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 141433, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x480A1D80U)}, PosB = new Vector3() { x = RawToFloat(0x47A25D3CU), y = RawToFloat(0x00000000U), z = RawToFloat(0x47DF79A3U)}, PosC = new Vector3() { x = RawToFloat(0x2EB03393U), y = RawToFloat(0x00000000U), z = RawToFloat(0xC80A1D80U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 154586, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x4816F500U)}, PosB = new Vector3() { x = RawToFloat(0x47B175ECU), y = RawToFloat(0x00000000U), z = RawToFloat(0x47F440EDU)}, PosC = new Vector3() { x = RawToFloat(0x2EC0959FU), y = RawToFloat(0x00000000U), z = RawToFloat(0xC816F500U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 168025, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x48241500U)}, PosB = new Vector3() { x = RawToFloat(0x48241500U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2E51542AU)}, PosC = new Vector3() { x = RawToFloat(0xC8241500U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAE07BD7FU)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 181738, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x48317880U)}, PosB = new Vector3() { x = RawToFloat(0x48317880U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2E6268D3U)}, PosC = new Vector3() { x = RawToFloat(0xC8317880U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAE12D0F8U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 195715, PosA = new Vector3() { x = RawToFloat(0x469FD288U), y = RawToFloat(0x00000000U), z = RawToFloat(0x483E1379U)}, PosB = new Vector3() { x = RawToFloat(0x483F1F80U), y = RawToFloat(0x00000000U), z = RawToFloat(0x2E73D398U)}, PosC = new Vector3() { x = RawToFloat(0xC83F1F80U), y = RawToFloat(0x00000000U), z = RawToFloat(0xAE1E1C47U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 209946, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x484D0500U)}, PosB = new Vector3() { x = RawToFloat(0x48092F52U), y = RawToFloat(0x00000000U), z = RawToFloat(0x48185BF5U)}, PosC = new Vector3() { x = RawToFloat(0x2F02C70CU), y = RawToFloat(0x00000000U), z = RawToFloat(0xC84D0500U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 224422, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x485B2900U)}, PosB = new Vector3() { x = RawToFloat(0x4812A593U), y = RawToFloat(0x00000000U), z = RawToFloat(0x4822DE24U)}, PosC = new Vector3() { x = RawToFloat(0x2F0BCC2BU), y = RawToFloat(0x00000000U), z = RawToFloat(0xC85B2900U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 239136, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x48698680U)}, PosB = new Vector3() { x = RawToFloat(0x481C424DU), y = RawToFloat(0x00000000U), z = RawToFloat(0x482D8B0EU)}, PosC = new Vector3() { x = RawToFloat(0x2F14F5F7U), y = RawToFloat(0x00000000U), z = RawToFloat(0xC8698680U)} },
new PrecalculatedTriangle() { MaxOrbitRadius = 250000, PosA = new Vector3() { x = RawToFloat(0x00000000U), y = RawToFloat(0x00000000U), z = RawToFloat(0x48742180U)}, PosB = new Vector3() { x = RawToFloat(0x48235AFEU), y = RawToFloat(0x00000000U), z = RawToFloat(0x48356CB1U)}, PosC = new Vector3() { x = RawToFloat(0x2F1BB9CEU), y = RawToFloat(0x00000000U), z = RawToFloat(0xC8742180U)} },
];
struct PrecalculatedTriangle
{
public int MaxOrbitRadius;
public Vector3 PosA;
public Vector3 PosB;
public Vector3 PosC;
}
private static double RawToDouble(ulong value)
{
unsafe
{
return *(double*)&value;
}
}
private static float RawToFloat(uint value)
{
unsafe
{
return *(float*)&value;
}
}
public static void Init()
{
I18N.Add("You are not in any system.", "You are not in any system.", "你不在任何星系中");
I18N.Add("There is no Dyson Sphere shell on \"{0}\".", "There is no Dyson Sphere shell on \"{0}\".", "“{0}”上没有可建造的戴森壳");
I18N.Add("There is no Dyson Sphere data on \"{0}\".", "There is no Dyson Sphere data on \"{0}\".", "“{0}”上没有戴森球数据");
I18N.Add("This will complete all Dyson Sphere shells on \"{0}\" instantly. Are you sure?", "This will complete all Dyson Sphere shells on \"{0}\" instantly. Are you sure?", "这将立即完成“{0}”上的所有戴森壳。你确定吗?");
I18N.Add("No precalculated shell found for radius {0}.", "No precalculated shell found for radius {0}.", "没有找到适合半径 {0} 的预计算壳面");
}
public static void CompleteShellsInstantly()
@@ -250,23 +308,21 @@ public static class DysonSphereFunctions
}
private static readonly ThreadLocal<Dictionary<int, Vector3>> _vmap = new(() => new(16384));
private static int CalculateTriangleVertCount(VectorLF3[] polygon)
private static int CalculateTriangleVertCount(Vector3[] pos)
{
if (polygon.Length != 3) return -1;
if (pos.Length != 3) return -1;
VectorLF3[] polygon = [pos[0], pos[1], pos[2]];
VectorLF3 sum = VectorLF3.zero;
double num = 0.0;
for (int i = 0; i < 3; i++)
{
var nodeApos = polygon[i];
var nodeBpos = polygon[(i + 1) % 3];
float num2 = Vector3.Distance(nodeApos, nodeBpos);
VectorLF3 vectorLF2 = (VectorLF3)(nodeApos + nodeBpos) * 0.5;
sum += vectorLF2 * (double)num2;
num += (double)num2;
double num2 = Vector3.Distance(pos[i], pos[(i + 1) % 3]);
VectorLF3 vectorLF2 = ((VectorLF3)pos[i] + (VectorLF3)pos[(i + 1) % 3]) * 0.5;
sum += vectorLF2 * num2;
num += num2;
}
var radius = polygon[0].magnitude;
radius = Math.Round(radius * 10.0) / 10.0;
for (int j = 0; j < 3; j++)
var radius = Math.Round(polygon[0].magnitude * 10.0) / 10.0;
for (int j = 0; j < polygon.Length; j++)
{
polygon[j] = polygon[j].normalized * radius;
}
@@ -282,36 +338,34 @@ public static class DysonSphereFunctions
}
var gridScale = (int)(Math.Pow(radius / 4000.0, 0.75) + 0.5);
gridScale = ((gridScale < 1) ? 1 : gridScale);
var gridSize = (float)gridScale * 80f;
var gridSize = gridScale * 80f;
var gridSizeDouble = (double)gridSize;
var cpPerVertex = gridScale * gridScale * 2;
var num5 = (int)((double)num3 / 0.8660254037844386 / (double)gridSize + 2.5);
var num5 = (int)((double)num3 / factor3 / gridSizeDouble + 2.5);
var xaxis = VectorLF3.Cross(center, Vector3.up).normalized;
if (xaxis.magnitude < 0.1)
{
xaxis = new VectorLF3(0f, 0f, 1f);
}
var yaxis = VectorLF3.Cross(xaxis, center).normalized;
var raydir = xaxis * 0.915662593339561 + yaxis * 0.40194777665596015;
var w1axis = xaxis * (0.5 * (double)gridSize) - yaxis * (0.8660254037844386 * (double)gridSize);
var w2axis = xaxis * (0.5 * (double)gridSize) + yaxis * (0.8660254037844386 * (double)gridSize);
var w0axis = xaxis * (double)gridSize;
double num6 = 0.5773502691896258;
var t1axis = yaxis * ((double)gridSize * num6 * 0.5) - xaxis * ((double)gridSize * 0.5);
var t2axis = yaxis * ((double)gridSize * num6 * 0.5) + xaxis * ((double)gridSize * 0.5);
var t0axis = yaxis * ((double)gridSize / 0.8660254037844386 * 0.5);
var raydir = xaxis * factor0 + yaxis * factor1;
var w1axis = xaxis * (0.5 * gridSizeDouble) - yaxis * (factor3 * gridSizeDouble);
var w2axis = xaxis * (0.5 * gridSizeDouble) + yaxis * (factor3 * gridSizeDouble);
var w0axis = xaxis * gridSizeDouble;
var t1axis = yaxis * (gridSizeDouble * factor2 * 0.5) - xaxis * (gridSizeDouble * 0.5);
var t2axis = yaxis * (gridSizeDouble * factor2 * 0.5) + xaxis * (gridSizeDouble * 0.5);
var t0axis = yaxis * (gridSizeDouble / factor3 * 0.5);
var polyn = new VectorLF3[3];
var polynu = new double[3];
for (int l = 0; l < 3; l++)
{
Vector3 vector = polygon[l];
Vector3 vector2 = polygon[(l + 1) % 3];
polyn[l] = VectorLF3.Cross(vector, vector2).normalized;
polyn[l] = VectorLF3.Cross(polygon[l], polygon[(l + 1) % 3]).normalized;
polynu[l] = polyn[l].x * raydir.x + polyn[l].y * raydir.y + polyn[l].z * raydir.z;
}
var vmap = _vmap.Value;
vmap.Clear();
double num7 = (double)gridSize * 0.5;
double num7 = gridSizeDouble * 0.5;
for (int m = -num5; m <= num5; m++)
{
for (int n = -num5; n <= num5; n++)
@@ -319,13 +373,11 @@ public static class DysonSphereFunctions
if (m - n <= num5 && m - n >= -num5)
{
VectorLF3 vectorLF3;
vectorLF3.x = center.x + w0axis.x * (double)m - w1axis.x * (double)n;
vectorLF3.y = center.y + w0axis.y * (double)m - w1axis.y * (double)n;
vectorLF3.z = center.z + w0axis.z * (double)m - w1axis.z * (double)n;
double num8 = radius / Math.Sqrt(vectorLF3.x * vectorLF3.x + vectorLF3.y * vectorLF3.y + vectorLF3.z * vectorLF3.z);
vectorLF3.x *= num8;
vectorLF3.y *= num8;
vectorLF3.z *= num8;
vectorLF3.x = center.x + w0axis.x * m - w1axis.x * n;
vectorLF3.y = center.y + w0axis.y * m - w1axis.y * n;
vectorLF3.z = center.z + w0axis.z * m - w1axis.z * n;
double num8 = radius / vectorLF3.magnitude;
vectorLF3 *= num8;
int num9 = 0;
for (int num10 = 0; num10 < 3; num10++)
{
@@ -333,9 +385,7 @@ public static class DysonSphereFunctions
if (num11 >= 0.0)
{
VectorLF3 normalized2 = new VectorLF3(vectorLF3.x + num11 * raydir.x, vectorLF3.y + num11 * raydir.y, vectorLF3.z + num11 * raydir.z).normalized;
normalized2.x *= radius;
normalized2.y *= radius;
normalized2.z *= radius;
normalized2 *= radius;
VectorLF3 vectorLF4 = polygon[num10] - normalized2;
VectorLF3 vectorLF5 = polygon[(num10 + 1) % 3] - normalized2;
double num12 = vectorLF4.x * vectorLF5.x + vectorLF4.y * vectorLF5.y + vectorLF4.z * vectorLF5.z;
@@ -402,13 +452,12 @@ public static class DysonSphereFunctions
double num = 0.0;
for (int i = 0; i < shell.frames.Count; i++)
{
float num2 = Vector3.Distance(shell.frames[i].nodeA.pos, shell.frames[i].nodeB.pos);
VectorLF3 vectorLF2 = (VectorLF3)(shell.frames[i].nodeA.pos + shell.frames[i].nodeB.pos) * 0.5;
sum += vectorLF2 * (double)num2;
num += (double)num2;
double num2 = Vector3.Distance(shell.frames[i].nodeA.pos, shell.frames[i].nodeB.pos);
VectorLF3 vectorLF2 = ((VectorLF3)shell.frames[i].nodeA.pos + (VectorLF3)shell.frames[i].nodeB.pos) * 0.5;
sum += vectorLF2 * num2;
num += num2;
}
shell.radius = shell.polygon[0].magnitude;
shell.radius = Math.Round(shell.radius * 10.0) / 10.0;
shell.radius = Math.Round(shell.polygon[0].magnitude * 10.0) / 10.0;
for (int j = 0; j < shell.polygon.Count; j++)
{
shell.polygon[j] = shell.polygon[j].normalized * shell.radius;
@@ -426,37 +475,35 @@ public static class DysonSphereFunctions
}
shell.gridScale = (int)(Math.Pow(shell.radius / 4000.0, 0.75) + 0.5);
shell.gridScale = ((shell.gridScale < 1) ? 1 : shell.gridScale);
shell.gridSize = (float)shell.gridScale * 80f;
shell.gridSize = shell.gridScale * 80f;
var gridSizeDouble = (double)shell.gridSize;
shell.cpPerVertex = shell.gridScale * shell.gridScale * 2;
int num5 = (int)((double)num3 / 0.8660254037844386 / (double)shell.gridSize + 2.5);
int num5 = (int)((double)num3 / factor3 / gridSizeDouble + 2.5);
shell.xaxis = VectorLF3.Cross(normalized, Vector3.up).normalized;
if (shell.xaxis.magnitude < 0.1)
{
shell.xaxis = new VectorLF3(0f, 0f, 1f);
}
shell.yaxis = VectorLF3.Cross(shell.xaxis, normalized).normalized;
shell.raydir = shell.xaxis * 0.915662593339561 + shell.yaxis * 0.40194777665596015;
shell.w1axis = shell.xaxis * (0.5 * (double)shell.gridSize) - shell.yaxis * (0.8660254037844386 * (double)shell.gridSize);
shell.w2axis = shell.xaxis * (0.5 * (double)shell.gridSize) + shell.yaxis * (0.8660254037844386 * (double)shell.gridSize);
shell.w0axis = shell.xaxis * (double)shell.gridSize;
double num6 = 0.5773502691896258;
shell.t1axis = shell.yaxis * ((double)shell.gridSize * num6 * 0.5) - shell.xaxis * ((double)shell.gridSize * 0.5);
shell.t2axis = shell.yaxis * ((double)shell.gridSize * num6 * 0.5) + shell.xaxis * ((double)shell.gridSize * 0.5);
shell.t0axis = shell.yaxis * ((double)shell.gridSize / 0.8660254037844386 * 0.5);
shell.raydir = shell.xaxis * factor0 + shell.yaxis * factor1;
shell.w1axis = shell.xaxis * (0.5 * gridSizeDouble) - shell.yaxis * (factor3 * gridSizeDouble);
shell.w2axis = shell.xaxis * (0.5 * gridSizeDouble) + shell.yaxis * (factor3 * gridSizeDouble);
shell.w0axis = shell.xaxis * gridSizeDouble;
shell.t1axis = shell.yaxis * (gridSizeDouble * factor2 * 0.5) - shell.xaxis * (gridSizeDouble * 0.5);
shell.t2axis = shell.yaxis * (gridSizeDouble * factor2 * 0.5) + shell.xaxis * (gridSizeDouble * 0.5);
shell.t0axis = shell.yaxis * (gridSizeDouble / factor3 * 0.5);
int count = shell.polygon.Count;
shell.polyn = new VectorLF3[count];
shell.polynu = new double[count];
for (int l = 0; l < count; l++)
{
Vector3 vector = shell.polygon[l];
Vector3 vector2 = shell.polygon[(l + 1) % count];
shell.polyn[l] = VectorLF3.Cross(vector, vector2).normalized;
shell.polyn[l] = VectorLF3.Cross(shell.polygon[l], shell.polygon[(l + 1) % count]).normalized;
shell.polynu[l] = shell.polyn[l].x * shell.raydir.x + shell.polyn[l].y * shell.raydir.y + shell.polyn[l].z * shell.raydir.z;
}
DysonShell.s_vmap.Clear();
DysonShell.s_outvmap.Clear();
DysonShell.s_ivmap.Clear();
double num7 = (double)shell.gridSize * 0.5;
double num7 = gridSizeDouble * 0.5;
for (int m = -num5; m <= num5; m++)
{
for (int n = -num5; n <= num5; n++)
@@ -464,13 +511,11 @@ public static class DysonSphereFunctions
if (m - n <= num5 && m - n >= -num5)
{
VectorLF3 vectorLF3;
vectorLF3.x = shell.center.x + shell.w0axis.x * (double)m - shell.w1axis.x * (double)n;
vectorLF3.y = shell.center.y + shell.w0axis.y * (double)m - shell.w1axis.y * (double)n;
vectorLF3.z = shell.center.z + shell.w0axis.z * (double)m - shell.w1axis.z * (double)n;
double num8 = shell.radius / Math.Sqrt(vectorLF3.x * vectorLF3.x + vectorLF3.y * vectorLF3.y + vectorLF3.z * vectorLF3.z);
vectorLF3.x *= num8;
vectorLF3.y *= num8;
vectorLF3.z *= num8;
vectorLF3.x = shell.center.x + shell.w0axis.x * m - shell.w1axis.x * n;
vectorLF3.y = shell.center.y + shell.w0axis.y * m - shell.w1axis.y * n;
vectorLF3.z = shell.center.z + shell.w0axis.z * m - shell.w1axis.z * n;
double num8 = shell.radius / vectorLF3.magnitude;
vectorLF3 *= num8;
int num9 = 0;
for (int num10 = 0; num10 < count; num10++)
{
@@ -478,9 +523,7 @@ public static class DysonSphereFunctions
if (num11 >= 0.0)
{
VectorLF3 normalized2 = new VectorLF3(vectorLF3.x + num11 * shell.raydir.x, vectorLF3.y + num11 * shell.raydir.y, vectorLF3.z + num11 * shell.raydir.z).normalized;
normalized2.x *= shell.radius;
normalized2.y *= shell.radius;
normalized2.z *= shell.radius;
normalized2 *= shell.radius;
VectorLF3 vectorLF4 = shell.polygon[num10] - normalized2;
VectorLF3 vectorLF5 = shell.polygon[(num10 + 1) % count] - normalized2;
double num12 = vectorLF4.x * vectorLF5.x + vectorLF4.y * vectorLF5.y + vectorLF4.z * vectorLF5.z;
@@ -560,7 +603,7 @@ public static class DysonSphereFunctions
Vector3 value = keyValuePair.Value;
DysonShell.s_ivmap[keyValuePair.Key] = num21;
shell.verts[num21] = value;
shell.uv2s[num21].x = (float)(DysonShell.s_outvmap.ContainsKey(keyValuePair.Key) ? 0 : 1);
shell.uv2s[num21].x = DysonShell.s_outvmap.ContainsKey(keyValuePair.Key) ? 0 : 1;
shell.vkeys[num21] = keyValuePair.Key;
num21++;
}
@@ -631,7 +674,7 @@ public static class DysonSphereFunctions
num33 = num34;
}
}
shell.uv2s[num31].y = (float)num33;
shell.uv2s[num31].y = num33;
if (num29 + num30 < 49 && shell._is_point_in_shell(vectorLF14))
{
double num39 = VectorLF3.Dot(vectorLF14 - shell.polygon[num33], shell.polyn[num33]);
@@ -677,7 +720,7 @@ public static class DysonSphereFunctions
num47 = count3 - num47;
}
double num48 = (double)(vector3 - shell.nodes[num46].pos).sqrMagnitude;
num48 += (double)num47;
num48 += num47;
if (num48 < num42)
{
num42 = num48;
@@ -740,8 +783,8 @@ public static class DysonSphereFunctions
}
shell.vertsq[num58++] = (short)num61;
num60 += 1.0;
shell.uvs[num61].x = (float)num53;
shell.uvs[num61].y = (float)(num60 / (double)num59);
shell.uvs[num61].x = num53;
shell.uvs[num61].y = (float)(num60 / num59);
if (num58 == shell.vertsqOffset[num53 + 1])
{
goto Block_57;
@@ -756,8 +799,8 @@ public static class DysonSphereFunctions
{
shell.vertsq[num58++] = (short)num62;
num60 += 1.0;
shell.uvs[num62].x = (float)num53;
shell.uvs[num62].y = (float)(num60 / (double)num59);
shell.uvs[num62].x = num53;
shell.uvs[num62].y = (float)(num60 / num59);
}
}
}
@@ -842,7 +885,10 @@ public static class DysonSphereFunctions
layer.shellRecycle[recycleIndex] = shellId;
return 0;
}
CheatEnabler.Logger.LogDebug($"Shell {shellId} VertCount: {DysonShell.s_vmap.Count}");
// CheatEnabler.Logger.LogDebug($"Shell {shellId} My VertCount: {DysonShell.s_vmap.Count}");
// shell.GenerateGeometry();
// CheatEnabler.Logger.LogDebug($"Shell {shellId} Orig VertCount: {DysonShell.s_vmap.Count}");
// CheatEnabler.Logger.LogDebug($"Shell {shellId} Calc VertCount: {CalculateTriangleVertCount2([shell.nodes[0].pos, shell.nodes[1].pos, shell.nodes[2].pos])}");
for (int j = 0; j < shell.nodes.Count; j++)
{
shell.nodes[j].shells.Add(shell);
@@ -1112,6 +1158,104 @@ public static class DysonSphereFunctions
dysonSphere.modelRenderer.RebuildModels();
}
public static void CreateIllegalDysonShellQuickly(int triangleCount)
{
StarData star = null;
var dysonEditor = UIRoot.instance?.uiGame?.dysonEditor;
if (dysonEditor != null && dysonEditor.gameObject.activeSelf)
{
star = dysonEditor.selection.viewStar;
}
if (star == null)
{
star = GameMain.data?.localStar;
if (star == null)
{
UIMessageBox.Show("CheatEnabler".Translate(), "You are not in any system.".Translate(), "确定".Translate(), UIMessageBox.ERROR, null);
return;
}
}
var dysonSphere = GameMain.data?.dysonSpheres[star.index];
if (dysonSphere == null)
{
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere data on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null);
return;
}
DysonShell.s_vmap ??= new Dictionary<int, Vector3>(16384);
DysonShell.s_outvmap ??= new Dictionary<int, Vector3>(16384);
DysonShell.s_ivmap ??= new Dictionary<int, int>(16384);
for (int i = 1; i <= 10; i++)
{
var layer = dysonSphere.layersIdBased[i];
if (layer != null)
{
continue;
}
var radius = dysonSphere.maxOrbitRadius;
for (; radius > 4000; radius -= 10)
{
if (dysonSphere.CheckLayerRadius(radius) == 0)
{
break;
}
}
PrecalculatedTriangle triangle;
try
{
triangle = PrecalculatedTriangles.First(t => t.MaxOrbitRadius > radius);
}
catch (InvalidOperationException)
{
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("No precalculated triangle found for radius {0}.".Translate(), radius), "确定".Translate(), UIMessageBox.ERROR, null);
return;
}
layer = dysonSphere.AddLayerOnId(i, radius, Quaternion.Euler(0f, 0f, 0f), Mathf.Sqrt(dysonSphere.gravity / radius) / radius * 57.2957802f);
if (layer == null) return;
Vector3[] nodePos = [triangle.PosA.normalized * radius, triangle.PosB.normalized * radius, triangle.PosC.normalized * radius];
DysonNode[] nodes = [layer.QuickAddDysonNode(0, nodePos[0]), layer.QuickAddDysonNode(0, nodePos[1]), layer.QuickAddDysonNode(0, nodePos[2])];
DysonFrame[] frames = [layer.QuickAddDysonFrame(0, nodes[0], nodes[1], false), layer.QuickAddDysonFrame(0, nodes[1], nodes[2], false), layer.QuickAddDysonFrame(0, nodes[2], nodes[0], false)];
var shellId = layer.QuickAddDysonShell(0, nodes, frames, false);
if (shellId == 0) return;
var shell = layer.shellPool[shellId];
long[] cpMax = [.. nodes.Select(node => node.totalCpMax)];
long[] totalCpMax = [.. cpMax];
var dirtyFrames = new HashSet<int>();
for (var j = 1; j < triangleCount; j++)
{
dirtyFrames.Clear();
for (var k = 0; k < 3; k++)
{
totalCpMax[k] += cpMax[k];
if (totalCpMax[k] > int.MaxValue)
{
totalCpMax[k] = cpMax[k];
dirtyFrames.Add(k > 0 ? k - 1 : 2);
dirtyFrames.Add(k);
nodes[k] = layer.QuickAddDysonNode(0, nodePos[k]);
}
}
foreach (var frameId in dirtyFrames)
{
frames[frameId] = layer.QuickAddDysonFrame(0, nodes[frameId], nodes[(frameId + 1) % 3], false);
}
layer.QuickAddDysonShell(0, nodes, frames, false);
}
foreach (var node in nodes)
{
node.RecalcSpReq();
node.RecalcCpReq();
}
dysonSphere.CheckAutoNodes();
if (dysonSphere.autoNodeCount <= 0) dysonSphere.PickAutoNode();
dysonSphere.modelRenderer.RebuildModels();
GameMain.gameScenario.NotifyOnPlanDysonShell();
return;
}
}
public static void CreateIllegalDysonShellWithMaxOutput()
{
StarData star = null;
@@ -1153,10 +1297,10 @@ public static class DysonSphereFunctions
if (layer == null) return;
var supposedShells = new List<SupposedShell>(60 * 59 * 58);
VectorLF3[] nodePos = new VectorLF3[60];
Vector3[] nodePos = new Vector3[60];
for (var i = 0; i < 60; i++)
{
nodePos[i] = new VectorLF3(Math.Sin(Math.PI * 2 * i / 60), 0, Math.Cos(Math.PI * 2 * i / 60)) * layer.orbitRadius;
nodePos[i] = new Vector3((float)Math.Sin(Math.PI * 2 * i / 60), 0, (float)Math.Cos(Math.PI * 2 * i / 60)) * layer.orbitRadius;
}
for (var i = 0; i < 58; i++)
{
@@ -1246,6 +1390,169 @@ public static class DysonSphereFunctions
dysonSphere.inGameRenderMaskL = 0;
}
public static void CreateIllegalDysonShellsSpecially()
{
var lastGridScale = 0;
var radiusList = new List<int>();
for (var r = 4000; r <= 250000; r++)
{
var gridScale = (int)(Math.Pow(r / 4000.0, 0.75) + 0.5);
gridScale = (gridScale < 1) ? 1 : gridScale;
if (gridScale == lastGridScale) continue;
lastGridScale = gridScale;
radiusList.Add(r);
CheatEnabler.Logger.LogDebug($"Grid Scale: {gridScale} from {r}");
}
radiusList.Add(250000);
StarData star = null;
var dysonEditor = UIRoot.instance?.uiGame?.dysonEditor;
if (dysonEditor != null && dysonEditor.gameObject.activeSelf)
{
star = dysonEditor.selection.viewStar;
}
if (star == null)
{
star = GameMain.data?.localStar;
if (star == null)
{
UIMessageBox.Show("CheatEnabler".Translate(), "You are not in any system.".Translate(), "确定".Translate(), UIMessageBox.ERROR, null);
return;
}
}
UXAssist.Functions.DysonSphereFunctions.InitCurrentDysonLayer(star, 0);
var dysonSphere = GameMain.data?.dysonSpheres[star.index];
if (dysonSphere == null)
{
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere data on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null);
return;
}
DysonShell.s_vmap ??= new Dictionary<int, Vector3>(16384);
DysonShell.s_outvmap ??= new Dictionary<int, Vector3>(16384);
DysonShell.s_ivmap ??= new Dictionary<int, int>(16384);
var shellsChanged = false;
var mutex = new object();
for (var idx = 1; idx <= 2; idx++)
{
Dictionary<(int, int), int> availableFrames = [];
HashSet<int> unusedFrameIds = [];
var layer = dysonSphere.layersIdBased[idx];
if (layer != null)
{
dysonSphere.RemoveLayer(idx);
}
var orbitRadius = (radiusList[idx] - 1) / 10 * 10f;
layer = dysonSphere.AddLayerOnId(idx, orbitRadius, Quaternion.Euler(0f, 0f, 0f), Mathf.Sqrt(dysonSphere.gravity / orbitRadius) / orbitRadius * 57.2957802f);
if (layer == null) return;
var supposedShells = new List<SupposedShell>(60 * 59 * 58);
Vector3[] nodePos = new Vector3[60];
for (var i = 0; i < 60; i++)
{
nodePos[i] = new Vector3((float)Math.Sin(Math.PI * 2 * i / 60), 0, (float)Math.Cos(Math.PI * 2 * i / 60));
}
for (var i = 0; i < 58; i++)
{
for (var j = i + 1; j < 59; j++)
{
for (var k = j + 1; k < 60; k++)
{
var area = Vector3.Cross(nodePos[j] - nodePos[i], nodePos[k] - nodePos[i]).sqrMagnitude;
supposedShells.Add(new SupposedShell { posA = nodePos[i], posB = nodePos[j], posC = nodePos[k], area = area });
}
}
}
supposedShells.Sort((a, b) => b.area.CompareTo(a.area));
var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount - 1 };
var gridScale = (int)(Math.Pow(orbitRadius / 4000.0, 0.75) + 0.5);
gridScale = (gridScale < 1) ? 1 : gridScale;
var cpPerVertex = gridScale * gridScale * 2;
var barrier = 0x7FFFFFFF / cpPerVertex;
if (barrier > 30000) barrier = 30000;
Parallel.For(0, supposedShells.Count, options, (j, _) =>
{
var sshell = supposedShells[j];
var vertCount = CalculateTriangleVertCount([sshell.posA * orbitRadius, sshell.posB * orbitRadius, sshell.posC * orbitRadius]);
if (vertCount > barrier)
{
sshell.vertCount = -1;
}
else
{
sshell.vertCount = vertCount;
}
});
supposedShells.Sort((a, b) => b.vertCount.CompareTo(a.vertCount));
for (var j = 0; j < supposedShells.Count && supposedShells[j].vertCount > 0; j++)
{
var sshell = supposedShells[j];
CheatEnabler.Logger.LogDebug($"Checking Triangle {j}[{orbitRadius}] with {sshell.vertCount} vertices");
var result = Parallel.For((radiusList[idx - 1] + 9) / 10, (radiusList[idx] + 9) / 10, options, (k, loopState) =>
{
var orbitRadius = k * 10f;
var gridScale = (int)(Math.Pow(orbitRadius / 4000.0, 0.75) + 0.5);
gridScale = (gridScale < 1) ? 1 : gridScale;
var cpPerVertex = gridScale * gridScale * 2;
var barrier = 0x7FFFFFFF / cpPerVertex;
if (barrier > 31000) barrier = 31000;
if (loopState.ShouldExitCurrentIteration) return;
var vertCount = CalculateTriangleVertCount([sshell.posA * orbitRadius, sshell.posB * orbitRadius, sshell.posC * orbitRadius]);
lock (mutex)
{
if (loopState.ShouldExitCurrentIteration) return;
if (vertCount > barrier)
{
CheatEnabler.Logger.LogDebug($"EXCEEDED: Triangle {j}[{orbitRadius}] has {vertCount} vertices");
loopState.Stop();
}
}
});
if (!result.IsCompleted)
{
continue;
}
layer.nodePool = new DysonNode[64];
layer.nodeRecycle = new int[64];
layer.nodeRecycleCursor = 0;
layer.nodeCapacity = 64;
layer.nodeCursor = 1;
layer.framePool = new DysonFrame[64];
layer.frameRecycle = new int[64];
layer.frameRecycleCursor = 0;
layer.frameCapacity = 64;
layer.frameCursor = 1;
layer.shellPool = new DysonShell[64];
layer.shellRecycle = new int[64];
layer.shellRecycleCursor = 0;
layer.shellCapacity = 64;
layer.shellCursor = 1;
DysonNode[] newNodes = [layer.QuickAddDysonNode(0, sshell.posA * orbitRadius), layer.QuickAddDysonNode(0, sshell.posB * orbitRadius), layer.QuickAddDysonNode(0, sshell.posC * orbitRadius)];
DysonFrame[] newFrames = [layer.QuickAddDysonFrame(0, newNodes[0], newNodes[1], false), layer.QuickAddDysonFrame(0, newNodes[1], newNodes[2], false), layer.QuickAddDysonFrame(0, newNodes[2], newNodes[0], false)];
layer.QuickAddDysonShell(0, newNodes, newFrames, false);
foreach (var node in newNodes)
{
node.RecalcSpReq();
node.RecalcCpReq();
}
shellsChanged = true;
break;
}
}
dysonSphere.CheckAutoNodes();
if (dysonSphere.autoNodeCount <= 0) dysonSphere.PickAutoNode();
dysonSphere.modelRenderer.RebuildModels();
if (shellsChanged) GameMain.gameScenario.NotifyOnPlanDysonShell();
dysonSphere.inEditorRenderMaskS = 0;
dysonSphere.inEditorRenderMaskL = 0;
dysonSphere.inGameRenderMaskS = 0;
dysonSphere.inGameRenderMaskL = 0;
}
private static int AlignUpToPowerOfTwo(int value)
{
value--;
@@ -1259,10 +1566,11 @@ public static class DysonSphereFunctions
private class SupposedShell
{
public VectorLF3 posA;
public VectorLF3 posB;
public VectorLF3 posC;
public Vector3 posA;
public Vector3 posB;
public Vector3 posC;
public float area;
public int vertCount;
}
}
+2 -2
View File
@@ -30,7 +30,7 @@ public static class CombatPatch
MechaInvincible.Enable(false);
}
private class MechaInvincible: PatchImpl<MechaInvincible>
private class MechaInvincible : PatchImpl<MechaInvincible>
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(Player), nameof(Player.invincible), MethodType.Getter)]
@@ -65,7 +65,7 @@ public static class CombatPatch
}
}
private class BuildingsInvincible: PatchImpl<BuildingsInvincible>
private class BuildingsInvincible : PatchImpl<BuildingsInvincible>
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(SkillSystem), nameof(SkillSystem.DamageGroundObjectByLocalCaster))]
+11 -4
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;
@@ -59,6 +59,13 @@ public class DysonSpherePatch : PatchImpl<DysonSpherePatch>
UnlockMaxOrbitRadius.Enable(false);
}
// [HarmonyPostfix]
// [HarmonyPatch(typeof(DysonShell), nameof(DysonShell.ImportFromBlueprint))]
// private static void DysonShell_ImportFromBlueprint_Postfix(DysonShell __instance)
// {
// CheatEnabler.Logger.LogDebug($"[DysonShell.ImportFromBlueprint] vertCount={__instance.vertexCount}, cpPerVertex={__instance.cpPerVertex}, cpMax={__instance.cellPointMax}");
// }
[HarmonyTranspiler]
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.OrderConstructCp))]
private static IEnumerable<CodeInstruction> DysonNode_OrderConstructCp_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
@@ -127,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()
@@ -289,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;
+17 -24
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,25 +1123,18 @@ 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 = new();
private static readonly Dictionary<int, ItemSource> ItemSources = [];
private static bool _itemSourcesInitialized;
private class ItemSource
@@ -1212,7 +1205,7 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
for (var i = 0; i < len; i++)
{
if (ItemSources.ContainsKey(res[i])) continue;
var rs = new ItemSource { Count = rescnt[i], From = new Dictionary<int, float>() };
var rs = new ItemSource { Count = rescnt[i], From = [], Extra = null };
var it = recipe.Items;
var itcnt = recipe.ItemCounts;
var len2 = it.Length;
@@ -1223,7 +1216,7 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
if (len > 1)
{
rs.Extra = new Dictionary<int, float>();
rs.Extra = [];
for (var k = 0; k < len; k++)
{
if (i != k)
+9 -9
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;
@@ -187,7 +187,7 @@ public static class GamePatch
}
}
public class UnlockTech: PatchImpl<UnlockTech>
public class UnlockTech : PatchImpl<UnlockTech>
{
private static void UnlockTechRecursive(GameHistoryData history, [NotNull] TechProto techProto, int maxLevel = 10000)
{
@@ -282,7 +282,7 @@ public static class GamePatch
}
}
history.VarifyTechQueue();
history.VerifyTechQueue();
if (history.currentTech != history.techQueue[0])
{
history.currentTech = history.techQueue[0];
+2 -2
View File
@@ -29,7 +29,7 @@ public static class PlanetPatch
TerraformAnyway.Enable(false);
}
private class WaterPumperPatch: PatchImpl<WaterPumperPatch>
private class WaterPumperPatch : PatchImpl<WaterPumperPatch>
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.CheckBuildConditions))]
@@ -51,7 +51,7 @@ public static class PlanetPatch
}
}
private class TerraformAnyway: PatchImpl<TerraformAnyway>
private class TerraformAnyway : PatchImpl<TerraformAnyway>
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(BuildTool_Reform), nameof(BuildTool_Reform.ReformAction))]
+4 -4
View File
@@ -33,7 +33,7 @@ public static class PlayerPatch
WarpWithoutSpaceWarpers.Enable(false);
}
private class InstantHandCraft: PatchImpl<InstantHandCraft>
private class InstantHandCraft : PatchImpl<InstantHandCraft>
{
[HarmonyPostfix]
[HarmonyPatch(typeof(ForgeTask), MethodType.Constructor, typeof(int), typeof(int))]
@@ -43,7 +43,7 @@ public static class PlayerPatch
}
}
private class InstantTeleport: PatchImpl<InstantTeleport>
private class InstantTeleport : PatchImpl<InstantTeleport>
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(UIGlobemap), nameof(UIGlobemap._OnUpdate))]
@@ -66,7 +66,7 @@ public static class PlayerPatch
}
}
private class WarpWithoutSpaceWarpers: PatchImpl<WarpWithoutSpaceWarpers>
private class WarpWithoutSpaceWarpers : PatchImpl<WarpWithoutSpaceWarpers>
{
[HarmonyPrefix]
[HarmonyPatch(typeof(Mecha), nameof(Mecha.HasWarper))]
@@ -75,7 +75,7 @@ public static class PlayerPatch
__result = true;
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Mecha), nameof(Mecha.UseWarper))]
private static void Mecha_UseWarper_Postfix(ref bool __result)
+71 -38
View File
@@ -29,12 +29,12 @@ public static class ResourcePatch
FastMining.Enable(false);
}
private class InfiniteResource: PatchImpl<InfiniteResource>
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,48 +42,81 @@ public static class ResourcePatch
[HarmonyPatch(typeof(UIControlPanelVeinCollectorPanel), nameof(UIControlPanelVeinCollectorPanel._OnUpdate))]
[HarmonyPatch(typeof(UIMinerWindow), nameof(UIMinerWindow._OnUpdate))]
[HarmonyPatch(typeof(UIMiningUpgradeLabel), nameof(UIMiningUpgradeLabel.Update))]
[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(ci => (ci.opcode == OpCodes.Ldfld || ci.opcode == OpCodes.Ldflda) && ci.OperandIs(AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningCostRate))))
).Repeat(codeMatcher =>
{
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();
}
}
private class FastMining : PatchImpl<FastMining>
{
static private readonly float FastMiningSpeed = 2400f;
[HarmonyTranspiler]
[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.miningCostRate)))
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, 0f)
)
);
return matcher.InstructionEnumeration();
}
}
private class FastMining: PatchImpl<FastMining>
{
[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")]
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)))
).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();
}
+2 -2
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`才能看到后面两个按钮
* 生成单层仙术戴森壳
* 保留发电量最高的戴森壳并移除其他戴森壳
* 从发电量最高的壳复制戴森壳
+24 -3
View File
@@ -71,6 +71,8 @@ public static class UIConfigWindow
I18N.Add("Generate illegal dyson shell", "Generate an illegal dyson shell (!!All shells will be removed first!!)", "生成单层仙术戴森壳(!!会先删除全部的壳!!)");
I18N.Add("Keep max production shells and remove others", "Keep max production shells and remove others", "保留发电量最高的戴森壳并移除其他戴森壳");
I18N.Add("Duplicate shells from that with highest production", "Duplicate shells from that with highest production", "从发电量最高的壳复制戴森壳");
I18N.Add("Generate illegal dyson shell quickly", "Generate illegal dyson shell quickly", "快速生成仙术戴森壳");
I18N.Add("Shells count", "Shells count", "壳面数量");
I18N.Add("WARNING: This operation can be very slow, continue?", "WARNING: This operation can be very slow, continue?", "警告:此操作可能非常慢,继续吗?");
I18N.Add("WARNING: This operation is DANGEROUS, continue?", "WARNING: This operation is DANGEROUS, continue?", "警告:此操作非常危险,继续吗?");
I18N.Add("Terraform without enough soil piles", "Terraform without enough soil piles", "沙土不够时依然可以整改地形");
@@ -301,22 +303,37 @@ public static class UIConfigWindow
wnd.AddButton(x, y, 300f, tab4, "Complete Dyson Sphere shells instantly", 16, "button-complete-dyson-sphere-shells-instantly", DysonSphereFunctions.CompleteShellsInstantly);
{
y += 72f;
var btn1 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell", 16, "button-generate-illegal-dyson-shells", () => {
var originalY = y;
var btn1 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell", 16, "button-generate-illegal-dyson-shells", () =>
{
UIMessageBox.Show("Generate illegal dyson shell".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
() => { DysonSphereFunctions.CreateIllegalDysonShellWithMaxOutput(); });
});
y += 36f;
var btn2 = wnd.AddButton(x, y, 300f, tab4, "Keep max production shells and remove others", 16, "button-keep-max-production-shells", () => {
var btn2 = wnd.AddButton(x, y, 300f, tab4, "Keep max production shells and remove others", 16, "button-keep-max-production-shells", () =>
{
UIMessageBox.Show("Keep max production shells and remove others".Translate(), "WARNING: This operation is DANGEROUS, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
() => { DysonSphereFunctions.KeepMaxProductionShells(); });
});
y += 36f;
var btn3 = wnd.AddButton(x, y, 300f, tab4, "Duplicate shells from that with highest production", 16, "button-duplicate-shells-from-the-highest-production", () => {
var btn3 = wnd.AddButton(x, y, 300f, tab4, "Duplicate shells from that with highest production", 16, "button-duplicate-shells-from-the-highest-production", () =>
{
UIMessageBox.Show("Duplicate shells from that with highest production".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
() => { DysonSphereFunctions.DuplicateShellsWithHighestProduction(); });
});
y += 30f;
var slider1 = wnd.AddSlider(x + 20f, y, tab4, DysonSphereFunctions.ShellsCountForFunctions, new ShellsCountMapper());
y = originalY;
var btn4 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell quickly", 16, "button-generate-illegal-dyson-shells-quickly", () =>
{
UIMessageBox.Show("Generate illegal dyson shell".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
() => { DysonSphereFunctions.CreateIllegalDysonShellQuickly(DysonSphereFunctions.ShellsCountForFunctions.Value); });
});
y += 30f;
var txt2 = wnd.AddText2(x, y, tab4, "Shells count", 15, "text-shells-count");
var slider2 = wnd.AddSlider(x + txt2.preferredWidth + 5f, y + 6f, tab4, DysonSphereFunctions.ShellsCountForFunctions, new ShellsCountMapper());
Functions.DysonSphereFunctions.IllegalDysonShellFunctionsEnabled.SettingChanged += onIllegalDysonShellFunctionsChanged;
wnd.OnFree += () => { Functions.DysonSphereFunctions.IllegalDysonShellFunctionsEnabled.SettingChanged -= onIllegalDysonShellFunctionsChanged; };
onIllegalDysonShellFunctionsChanged(null, null);
@@ -327,6 +344,10 @@ public static class UIConfigWindow
btn2.gameObject.SetActive(enabled);
btn3.gameObject.SetActive(enabled);
slider1.gameObject.SetActive(enabled);
btn4.gameObject.SetActive(!enabled);
txt2.gameObject.SetActive(!enabled);
slider2.gameObject.SetActive(!enabled);
}
}
+2 -2
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"
]
}
+7 -7
View File
@@ -1,8 +1,10 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UXAssist", "UXAssist\UXAssist.csproj", "{9C048229-6A50-4642-BC5E-02CD39D3869A}"
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
@@ -28,8 +30,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DustbinPreloader", "Dustbin
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoolOpt", "PoolOpt\PoolOpt.csproj", "{8BE61246-2C9D-4088-AA33-5AFF22C5046E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UXAssist", "UXAssist\UXAssist.csproj", "{9C048229-6A50-4642-BC5E-02CD39D3869A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserCloak", "UserCloak\UserCloak.csproj", "{096D2E4B-D1CE-424D-9954-C36A23E9E279}"
EndProject
Global
@@ -38,6 +38,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|Any CPU.Build.0 = Release|Any CPU
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -82,10 +86,6 @@ Global
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|Any CPU.Build.0 = Release|Any CPU
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|Any CPU.Build.0 = Release|Any CPU
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|Any CPU.Build.0 = Debug|Any CPU
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|Any CPU.ActiveCfg = Release|Any CPU
+1 -1
View File
@@ -52,7 +52,7 @@ public static class BeltSignal
tex.LoadImage(fileData);
return tex;
}
private static Sprite LoadEmbeddedSprite(string path, Assembly assembly = null)
{
var tex = LoadEmbeddedTexture(path, assembly);
+12 -12
View File
@@ -61,19 +61,19 @@ namespace Dustbin.NebulaSupport
NebulaModAPI.MultiplayerSession.Network.SendPacket(new SyncPlanetData(Dustbin.ExportData(factory)));
return;
case < 0:
{
var tankPool = factory.factoryStorage.tankPool;
tankPool[-storageId].IsDustbin = packet.Enable;
TankPatch.Reset();
return;
}
{
var tankPool = factory.factoryStorage.tankPool;
tankPool[-storageId].IsDustbin = packet.Enable;
TankPatch.Reset();
return;
}
case > 0:
{
var storagePool = factory.factoryStorage.storagePool;
storagePool[storageId].IsDustbin = packet.Enable;
StoragePatch.Reset();
return;
}
{
var storagePool = factory.factoryStorage.storagePool;
storagePool[storageId].IsDustbin = packet.Enable;
StoragePatch.Reset();
return;
}
}
}
}
+2 -2
View File
@@ -13,7 +13,7 @@ public static class StoragePatch
private static UI.MyCheckBox _storageDustbinCheckBox;
private static int _lastStorageId;
private static Harmony _patch;
public static void Enable(bool on)
{
if (on)
@@ -138,7 +138,7 @@ public static class StoragePatch
_storageDustbinCheckBox.rectTrans.anchoredPosition3D = new Vector3(190, 57 - rectTrans.sizeDelta.y, 0);
}
}
/* Adopt fix from starfi5h's NebulaCompatiblilityAssist */
[HarmonyPostfix]
[HarmonyPatch(typeof(UIStorageGrid), nameof(UIStorageGrid.OnStorageSizeChanged))]
+1 -1
View File
@@ -11,7 +11,7 @@ public static class TankPatch
private static UI.MyCheckBox _tankDustbinCheckBox;
private static int _lastTankId;
private static Harmony _patch;
public static void Enable(bool on)
{
if (on)
+1 -1
View File
@@ -7,7 +7,7 @@ namespace DustbinPreloader;
public static class Preloader
{
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("Dustbin Preloader");
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("Dustbin Preloader");
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
public static void Patch(AssemblyDefinition assembly)
+8 -8
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;
+67 -67
View File
@@ -410,30 +410,30 @@ public static class LabOptPatchFunctions
public static void SetFunctionInternal(ref LabComponent lab, bool researchMode, int recpId, int techId, SignData[] signPool, LabComponent[] labPool)
{
// LabOptPatch.Logger.LogDebug($"SetFunctionInternal: id={lab.id} root={(int)RootLabIdField.GetValue(lab)} research={researchMode} recp={recpId} tech={techId}");
lab.replicating = false;
lab.time = 0;
lab.hashBytes = 0;
lab.extraHashBytes = 0;
lab.extraTime = 0;
lab.extraSpeed = 0;
lab.extraPowerRatio = 0;
lab.productive = false;
if (researchMode)
{
lab.forceAccMode = false;
lab.researchMode = true;
lab.recipeId = 0;
lab.techId = 0;
lab.timeSpend = 0;
lab.extraTimeSpend = 0;
lab.requires = null;
lab.requireCounts = null;
lab.served = null;
lab.incServed = null;
lab.products = null;
lab.productCounts = null;
lab.produced = null;
lab.productive = true;
lab.replicating = false;
lab.time = 0;
lab.hashBytes = 0;
lab.extraHashBytes = 0;
lab.extraTime = 0;
lab.extraSpeed = 0;
lab.extraPowerRatio = 0;
lab.productive = false;
if (researchMode)
{
lab.forceAccMode = false;
lab.researchMode = true;
lab.recipeId = 0;
lab.techId = 0;
lab.timeSpend = 0;
lab.extraTimeSpend = 0;
lab.requires = null;
lab.requireCounts = null;
lab.served = null;
lab.incServed = null;
lab.products = null;
lab.productCounts = null;
lab.produced = null;
lab.productive = true;
var rootLabId = lab.pcId;
if (rootLabId > 0)
{
@@ -480,29 +480,29 @@ public static class LabOptPatchFunctions
}
}
signPool[lab.entityId].iconId0 = (uint)lab.techId;
signPool[lab.entityId].iconType = lab.techId == 0 ? 0U : 3U;
return;
}
lab.researchMode = false;
lab.recipeId = 0;
lab.techId = 0;
lab.matrixPoints = null;
lab.matrixServed = null;
lab.matrixIncServed = null;
RecipeProto recipeProto = null;
if (recpId > 0)
{
recipeProto = LDB.recipes.Select(recpId);
}
if (recipeProto != null && recipeProto.Type == ERecipeType.Research)
{
lab.recipeId = recipeProto.ID;
lab.speed = 10000;
lab.speedOverride = lab.speed;
lab.timeSpend = recipeProto.TimeSpend * 10000;
lab.extraTimeSpend = recipeProto.TimeSpend * 100000;
lab.productive = recipeProto.productive;
lab.forceAccMode &= lab.productive;
signPool[lab.entityId].iconType = lab.techId == 0 ? 0U : 3U;
return;
}
lab.researchMode = false;
lab.recipeId = 0;
lab.techId = 0;
lab.matrixPoints = null;
lab.matrixServed = null;
lab.matrixIncServed = null;
RecipeProto recipeProto = null;
if (recpId > 0)
{
recipeProto = LDB.recipes.Select(recpId);
}
if (recipeProto != null && recipeProto.Type == ERecipeType.Research)
{
lab.recipeId = recipeProto.ID;
lab.speed = 10000;
lab.speedOverride = lab.speed;
lab.timeSpend = recipeProto.TimeSpend * 10000;
lab.extraTimeSpend = recipeProto.TimeSpend * 100000;
lab.productive = recipeProto.productive;
lab.forceAccMode &= lab.productive;
var rootLabId = lab.pcId;
if (rootLabId > 0)
{
@@ -544,26 +544,26 @@ public static class LabOptPatchFunctions
Array.Clear(lab.produced, 0, lab.produced.Length);
}
}
else
{
lab.forceAccMode = false;
lab.recipeId = 0;
lab.speed = 0;
lab.speedOverride = 0;
lab.timeSpend = 0;
lab.extraTimeSpend = 0;
lab.requires = null;
lab.requireCounts = null;
lab.served = null;
lab.incServed = null;
lab.needs = null;
lab.products = null;
lab.productCounts = null;
lab.produced = null;
}
signPool[lab.entityId].iconId0 = (uint)lab.recipeId;
signPool[lab.entityId].iconType = lab.recipeId == 0 ? 0U : 2U;
}
else
{
lab.forceAccMode = false;
lab.recipeId = 0;
lab.speed = 0;
lab.speedOverride = 0;
lab.timeSpend = 0;
lab.extraTimeSpend = 0;
lab.requires = null;
lab.requireCounts = null;
lab.served = null;
lab.incServed = null;
lab.needs = null;
lab.products = null;
lab.productCounts = null;
lab.produced = null;
}
signPool[lab.entityId].iconId0 = (uint)lab.recipeId;
signPool[lab.entityId].iconType = lab.recipeId == 0 ? 0U : 2U;
}
public static int InsertIntoLab(PlanetFactory factory, int labId, int itemId, byte itemCount, byte itemInc, ref byte remainInc, int[] needs)
{
+3 -3
View File
@@ -18,7 +18,7 @@ public class LabOptPatch : BaseUnityPlugin
{
Harmony.CreateAndPatchAll(typeof(LabOptPatch));
}
// Patch LabComponent.Export() to save zero value if rootLabId > 0.
[HarmonyTranspiler]
[HarmonyPatch(typeof(LabComponent), nameof(LabComponent.Export))]
@@ -274,7 +274,7 @@ public class LabOptPatch : BaseUnityPlugin
);
return matcher.InstructionEnumeration();
}
// Change locks on PlanetFactory.InsertInto(), by calling LabOptPatchFunctions.InsertIntoLab()
[HarmonyTranspiler]
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.InsertInto))]
@@ -332,7 +332,7 @@ public class LabOptPatch : BaseUnityPlugin
{
LabOptPatchFunctions.SetRootId(ref __instance, 0);
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetRootId))]
[HarmonyPatch(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetRootLabIdForStacking))]
+1 -1
View File
@@ -7,7 +7,7 @@ namespace LabOptPreloader;
public static class Preloader
{
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("LabOpt Preloader");
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("LabOpt Preloader");
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
public static void Patch(AssemblyDefinition assembly)
+57
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));
}
}
+39
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>
+33
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
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);
}
}
+325
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();
}
}
+123
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
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则关闭燃料补充能量功能。
+10
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"
]
}
-485
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);
}
}
}
-25
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>
-50
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则关闭燃料补充能量功能。
-9
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"
]
}
+3 -3
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)
+544 -500
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -3,7 +3,7 @@ using HarmonyLib;
namespace UXAssist.Common;
public class GameLogic: PatchImpl<GameLogic>
public class GameLogic : PatchImpl<GameLogic>
{
public static Action OnDataLoaded;
public static Action OnGameBegin;
+2 -2
View File
@@ -122,14 +122,14 @@ public static class I18N
_initialized = true;
Apply();
}
[HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.LoadLanguage))]
private static void Localization_LoadLanguage_Postfix(int index)
{
if (!_initialized) return;
ApplyLanguage(index);
}
[HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.NotifyLanguageChange))]
private static void Localization_NotifyLanguageChange_Postfix()
{
+4 -4
View File
@@ -36,13 +36,13 @@ public static class Util
tex.LoadImage(fileData);
return tex;
}
public static Sprite LoadSprite(string path)
{
var tex = LoadTexture(path);
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
}
public static Texture2D LoadEmbeddedTexture(string path, Assembly assembly = null)
{
var fileData = LoadEmbeddedResource(path, assembly);
@@ -50,12 +50,12 @@ public static class Util
tex.LoadImage(fileData);
return tex;
}
public static Sprite LoadEmbeddedSprite(string path, Assembly assembly = null)
{
var tex = LoadEmbeddedTexture(path, assembly);
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
}
public static string PluginFolder(Assembly assembly = null) => Path.GetDirectoryName((assembly == null ? Assembly.GetCallingAssembly() : assembly).Location);
}
+1 -129
View File
@@ -127,13 +127,10 @@ public static class WinApi
[DllImport("user32", ExactSpelling = true)]
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
[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
}
+3 -2
View File
@@ -13,7 +13,8 @@ public static class FactoryFunctions
// Clear entity connection
var factory = cargoTraffic.factory;
factory.ReadObjectConn(belt.entityId, 0, out var isOutput, out var otherObjId, out var otherSlot);
if (isOutput && factory.entityPool[otherObjId].beltId == belt.outputId) {
if (isOutput && factory.entityPool[otherObjId].beltId == belt.outputId)
{
factory.ClearObjectConnDirect(belt.entityId, 0);
factory.ClearObjectConnDirect(otherObjId, otherSlot);
}
@@ -194,7 +195,7 @@ public static class FactoryFunctions
bpBuildings.Add(new BPBuildingData { building = building, itemType = itemType, offset = offset });
}
}
var beltsWithInput = bpBelts.Select(pair => pair.Value.building.outputObj).ToHashSet();
HashSet<BlueprintBuilding> beltsWithInput = [.. bpBelts.Select(pair => pair.Value.building.outputObj)];
var beltHeads = bpBelts.Where(pair => !beltsWithInput.Contains(pair.Value.building)).ToDictionary(pair => pair.Key, pair => pair.Value);
// Sort belt buildings
List<BlueprintBuilding> sortedBpBelts = [];
+3 -2
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();
@@ -173,7 +173,8 @@ public static class PlanetFunctions
{
ref var warning = ref warningPool[i];
if (warning.id != i) continue;
switch (warning.factoryId) {
switch (warning.factoryId)
{
case -4:
if (warning.astroId == planetId)
warningSystem.RemoveWarningData(i);
+1 -1
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];
+7 -7
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:
-84
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
@@ -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;
}
}
+8 -8
View File
@@ -5,11 +5,11 @@ using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine.UI;
using UXAssist.Common;
using GameLogic = UXAssist.Common.GameLogic;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UXAssist.Patches;
public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
public class DysonSpherePatch : PatchImpl<DysonSpherePatch>
{
public static ConfigEntry<bool> StopEjectOnNodeCompleteEnabled;
public static ConfigEntry<bool> OnlyConstructNodesEnabled;
@@ -261,7 +261,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
return matcher.InstructionEnumeration();
}
private class StopEjectOnNodeComplete: PatchImpl<StopEjectOnNodeComplete>
private class StopEjectOnNodeComplete : PatchImpl<StopEjectOnNodeComplete>
{
private static HashSet<int>[] _nodeForAbsorb;
private static bool _initialized;
@@ -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;
}
@@ -492,7 +492,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
}
[PatchSetCallbackFlag(PatchCallbackFlag.CallOnDisableAfterUnpatch)]
private class OnlyConstructNodes: PatchImpl<OnlyConstructNodes>
private class OnlyConstructNodes : PatchImpl<OnlyConstructNodes>
{
protected override void OnEnable()
{
+109 -107
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);
}
}
}
+5 -172
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;
@@ -80,17 +78,13 @@ public class GamePatch : PatchImpl<GamePatch>
I18N.Add("Logical frame rate: {0}x", "[UXA] Logical frame rate: {0}x", "[UXA] 逻辑帧速率: {0}x");
EnableWindowResizeEnabled.SettingChanged += (_, _) => EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
LoadLastWindowRectEnabled.SettingChanged += (_, _) => {
LoadLastWindowRectEnabled.SettingChanged += (_, _) =>
{
if (LoadLastWindowRectEnabled.Value)
{
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();
@@ -122,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);
@@ -135,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);
}
@@ -159,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;
@@ -230,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;
@@ -257,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;
@@ -281,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;
@@ -600,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();
}
}
}
+91 -61
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);
@@ -298,7 +298,8 @@ public static class LogisticsPatch
new CodeMatch(OpCodes.Ldc_I4_1),
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(GameMain), nameof(GameMain.mainPlayer)))
);
if (matcher.IsValid) {
if (matcher.IsValid)
{
matcher.RemoveInstructions(7).InsertAndAdvance(
new CodeInstruction(OpCodes.Ldc_I4_0)
);
@@ -718,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;
@@ -726,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;
@@ -768,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)
@@ -787,7 +796,9 @@ public static class LogisticsPatch
public static void OnGameBegin()
{
_lastPlanet = null;
RecycleStationTips();
_lastPlanetId = 0;
_stationTipsRoot?.SetActive(false);
}
public static void OnDataLoaded()
@@ -841,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>();
@@ -992,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()
@@ -1011,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)
@@ -1032,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)
@@ -1055,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;
@@ -1087,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;
@@ -1134,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
@@ -1164,7 +1192,6 @@ public static class LogisticsPatch
}
}
public class StationTip : MonoBehaviour
{
[FormerlySerializedAs("RectTransform")]
@@ -1208,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,
@@ -1391,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;
@@ -1410,8 +1431,13 @@ public static class LogisticsPatch
);
_sliderCurrent[i].gameObject.SetActive(true);
}
barPositionChanged = true;
}
}
else
{
if (itemCount > itemLimit) itemCount = itemLimit;
}
if (barEnabled)
{
@@ -1419,6 +1445,10 @@ public static class LogisticsPatch
if (storageState.ItemOrdered != itemOrdered)
{
storageState.ItemOrdered = itemOrdered;
barPositionChanged = true;
}
if (barPositionChanged)
{
switch (itemOrdered)
{
case > 0:
@@ -1433,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;
@@ -1458,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
+1 -27
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))]
+2 -2
View File
@@ -24,7 +24,7 @@ public static class PlanetPatch
PlayerActionsInGlobeView.Enable(false);
}
public class PlayerActionsInGlobeView: PatchImpl<PlayerActionsInGlobeView>
public class PlayerActionsInGlobeView : PatchImpl<PlayerActionsInGlobeView>
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(VFInput), nameof(VFInput.UpdateGameStates))]
@@ -48,7 +48,7 @@ public static class PlanetPatch
});
return matcher.InstructionEnumeration();
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(PlayerController), nameof(PlayerController.GetInput))]
private static IEnumerable<CodeInstruction> PlayerController_GetInput_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
+6 -6
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);
}
}
@@ -287,7 +287,7 @@ public static class TechPatch
}
}
private class BatchBuyoutTech: PatchImpl<BatchBuyoutTech>
private class BatchBuyoutTech : PatchImpl<BatchBuyoutTech>
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(UITechNode), nameof(UITechNode.UpdateInfoDynamic))]
+318 -2
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 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
+18 -18
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>
+6 -6
View File
@@ -17,12 +17,12 @@ public class MyCheckButton : MonoBehaviour
private static GameObject _baseObject;
private static Color openMouseOverColor;
private static Color openPressColor;
private static Color openNormalColor;
private static Color closeMouseOverColor;
private static Color closePressColor;
private static Color closeNormalColor;
private static Color openMouseOverColor;
private static Color openPressColor;
private static Color openNormalColor;
private static Color closeMouseOverColor;
private static Color closePressColor;
private static Color closeNormalColor;
public static void InitBaseObject()
{
+1
View File
@@ -18,6 +18,7 @@ public class MyFlatButton : MonoBehaviour
var panel = UIRoot.instance.uiGame.dysonEditor.controlPanel.hierarchy.layerPanel;
var go = Instantiate(panel.layerButtons[0].gameObject);
var btn = go.GetComponent<UIButton>();
go.GetComponent<Image>().sprite = panel.buttonDefaultSprite;
btn.gameObject.name = "my-flatbutton";
btn.highlighted = false;
var img = btn.GetComponent<Image>();
+9 -6
View File
@@ -228,7 +228,7 @@ public class MyWindow : ManualBehaviour
return comboBox;
}
#region Slider
#region Slider
public class ValueMapper<T>
{
public virtual int Min => 1;
@@ -402,7 +402,7 @@ public class MyWindow : ManualBehaviour
{
return AddSideSlider(x, y, parent, config, new ArrayMapper<T>(valueList), format, width);
}
#endregion
#endregion
public InputField AddInputField(float x, float y, RectTransform parent, string text = "", int fontSize = 16, string objName = "input", UnityAction<string> onChanged = null,
UnityAction<string> onEditEnd = null)
@@ -475,8 +475,11 @@ public class MyWindowWithTabs : MyWindow
var swarmPanel = UIRoot.instance.uiGame.dysonEditor.controlPanel.hierarchy.swarmPanel;
var src = swarmPanel.orbitButtons[0];
var btn = Instantiate(src);
var btnRect = Util.NormalizeRectWithTopLeft(btn, Margin, y, parent);
btn.gameObject.GetComponent<Image>().sprite = swarmPanel.buttonDefaultSprite;
btn.name = "tab-btn-" + index;
btn.highlighted = false;
var btnRect = Util.NormalizeRectWithTopLeft(btn, Margin, y, parent);
btnRect.sizeDelta = new Vector2(TabWidth, TabHeight);
btn.transform.Find("frame").gameObject.SetActive(false);
if (btn.transitions.Length >= 3)
@@ -590,7 +593,7 @@ public abstract class MyWindowManager
}
*/
public class Patch: PatchImpl<Patch>
public class Patch : PatchImpl<Patch>
{
protected override void OnEnable()
{
@@ -610,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()
{
}
@@ -635,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)
+7 -33
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");
+13 -16
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();
}
}
+4 -6
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>
+1 -1
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": [
+3 -4
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;
}
+4
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
* (再次)修复新建游戏或加载存档时宇宙设置没有应用的问题
* 进入宇宙创建界面时重置星系间距/扁平度设置
+3 -3
View File
@@ -75,7 +75,7 @@ public static class EpicDifficulty
}
return 0;
}
public static int OilMultipliersCount()
{
return OilMultipliers.Length;
@@ -111,7 +111,7 @@ public static class EpicDifficulty
__instance.UpdateParametersUIDisplay();
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(UIGalaxySelect), nameof(UIGalaxySelect.UpdateParametersUIDisplay))]
private static bool UIGalaxySelect_UpdateParametersUIDisplay_Prefix(UIGalaxySelect __instance)
@@ -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);
+36 -49
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]
+3 -3
View File
@@ -19,15 +19,15 @@ public class UniverseGenTweaks : BaseUnityPlugin, IModCanSave
MoreSettings.Enabled = Config.Bind("MoreSettings", "Enabled", true, "Enable more settings on Universe Generation");
MoreSettings.MaxStarCount = Config.Bind("MoreSettings", "MaxStarCount", 128,
new ConfigDescription("(32 ~ 1024)\nMaximum star count for Universe Generation, enable MoreSettings.Enabled to take effect",
new AcceptableValueRange<int>(32, 1024), new {}));
new AcceptableValueRange<int>(32, 1024), new { }));
EpicDifficulty.Enabled = Config.Bind("EpicDifficulty", "Enabled", true, "Enable Epic difficulty");
EpicDifficulty.ResourceMultiplier = Config.Bind("EpicDifficulty", "ResourceMultiplier", 0.01f,
new ConfigDescription("Resource multiplier for Epic difficulty",
new AcceptableValueRange<float>(0.0001f, 0.05f), new {}));
new AcceptableValueRange<float>(0.0001f, 0.05f), new { }));
EpicDifficulty.OilMultiplier = Config.Bind("EpicDifficulty", "OilMultiplier", 0.5f,
new ConfigDescription("Oil multiplier for Epic difficulty relative to the Very-Hard difficulty",
new AcceptableValueRange<float>(0.1f, 1f), new {}));
new AcceptableValueRange<float>(0.1f, 1f), new { }));
BirthPlanetPatch.SitiVeinsOnBirthPlanet = Config.Bind("Birth", "SiTiVeinsOnBirthPlanet", false,
"Silicon/Titanium on birth planet");
+12 -3
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>
+1 -1
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": [
+1 -1
View File
@@ -8,7 +8,7 @@ using Random = UnityEngine.Random;
namespace UserCloak;
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
public class UserCloak: BaseUnityPlugin
public class UserCloak : BaseUnityPlugin
{
private static Harmony _patch;
private static ConfigEntry<int> _mode;