From 2dce3a7b93343216f24111dd3d053c8763f74b6b Mon Sep 17 00:00:00 2001 From: Soar Qin Date: Tue, 23 Jun 2026 04:10:09 +0800 Subject: [PATCH] refactor(CheatEnabler): split DysonSphereFunctions into focused helpers --- .../DysonSphere/DysonSphereResolver.cs | 52 + .../DysonSphere/FrameRemovalFunctions.cs | 58 + .../Functions/DysonSphere/GeometryHelpers.cs | 788 ++++++++ .../DysonSphere/IllegalShellFunctions.cs | 623 ++++++ .../DysonSphere/ShellCompletionFunctions.cs | 133 ++ .../Functions/DysonSphereFunctions.cs | 1690 +---------------- 6 files changed, 1664 insertions(+), 1680 deletions(-) create mode 100644 CheatEnabler/Functions/DysonSphere/DysonSphereResolver.cs create mode 100644 CheatEnabler/Functions/DysonSphere/FrameRemovalFunctions.cs create mode 100644 CheatEnabler/Functions/DysonSphere/GeometryHelpers.cs create mode 100644 CheatEnabler/Functions/DysonSphere/IllegalShellFunctions.cs create mode 100644 CheatEnabler/Functions/DysonSphere/ShellCompletionFunctions.cs diff --git a/CheatEnabler/Functions/DysonSphere/DysonSphereResolver.cs b/CheatEnabler/Functions/DysonSphere/DysonSphereResolver.cs new file mode 100644 index 0000000..073da70 --- /dev/null +++ b/CheatEnabler/Functions/DysonSphere/DysonSphereResolver.cs @@ -0,0 +1,52 @@ +using System; +using UnityEngine; +using UXAssist.Common; +using UXAssist.Common.ModFeatures; + +namespace CheatEnabler.Functions.DysonSphere; + +[ModFeature("DysonSphereResolver")] +public static class DysonSphereResolver +{ + public static (global::DysonSphere sphere, StarData star)? ResolveCurrent() + { + var star = GameMain.localStar; + if (star == null) return null; + var sphere = GameMain.data.dysonSpheres[star.index]; + if (sphere == null) return null; + return (sphere, star); + } + + public static StarData ResolveEditorOrLocalStar() + { + var dysonEditor = UIRoot.instance?.uiGame?.dysonEditor; + if (dysonEditor != null && dysonEditor.gameObject.activeSelf) + { + return dysonEditor.selection.viewStar; + } + var star = GameMain.localStar; + if (star == null) + { + UIMessageBox.Show("CheatEnabler".Translate(), "You are not in any system.".Translate(), "确定".Translate(), UIMessageBox.ERROR, null); + } + return star; + } + + public static (global::DysonSphere sphere, StarData star)? ResolveEditorOrLocalSphere(bool requireLayer = true) + { + var star = ResolveEditorOrLocalStar(); + if (star == null) return null; + var sphere = GameMain.data?.dysonSpheres[star.index]; + if (sphere == null) + { + UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere data on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null); + return null; + } + if (requireLayer && sphere.layerCount == 0) + { + UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null); + return null; + } + return (sphere, star); + } +} diff --git a/CheatEnabler/Functions/DysonSphere/FrameRemovalFunctions.cs b/CheatEnabler/Functions/DysonSphere/FrameRemovalFunctions.cs new file mode 100644 index 0000000..d13565e --- /dev/null +++ b/CheatEnabler/Functions/DysonSphere/FrameRemovalFunctions.cs @@ -0,0 +1,58 @@ +using System; +using HarmonyLib; +using UnityEngine; +using UXAssist.Common; +using UXAssist.Common.ModFeatures; + +namespace CheatEnabler.Functions.DysonSphere; + +[ModFeature("FrameRemovalFunctions")] +public static class FrameRemovalFunctions +{ + public static void RemoveAllFrames() + { + var resolved = DysonSphereResolver.ResolveEditorOrLocalSphere(); + if (resolved == null) return; + var (dysonSphere, star) = resolved.Value; + + UIMessageBox.Show("CheatEnabler".Translate(), string.Format("This will remove all frames on \"{0}\". Are you sure?".Translate(), star.displayName), "取消".Translate(), "确定".Translate(), UIMessageBox.QUESTION, null, () => + { + var totalFrameSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP"); + + foreach (var dysonSphereLayer in dysonSphere.layersIdBased) + { + if (dysonSphereLayer == null) continue; + for (var i = dysonSphereLayer.nodeCursor - 1; i >= 0; i--) + { + var dysonNode = dysonSphereLayer.nodePool[i]; + if (dysonNode == null || dysonNode.id != i) continue; + if (dysonNode.frames.Count > 0) + dysonNode.frames.Clear(); + dysonNode.RecalcSpReq(); + } + for (var i = dysonSphereLayer.shellCursor - 1; i >= 0; i--) + { + var dysonShell = dysonSphereLayer.shellPool[i]; + if (dysonShell == null || dysonShell.id != i) continue; + if (dysonShell.frames.Count > 0) + dysonShell.frames.Clear(); + } + for (var i = dysonSphereLayer.frameCursor - 1; i >= 0; i--) + { + var dysonFrame = dysonSphereLayer.framePool[i]; + if (dysonFrame == null || dysonFrame.id != i) continue; + dysonFrame.Free(); + dysonSphereLayer.framePool[i] = null; + } + dysonSphereLayer.frameCursor = 1; + dysonSphereLayer.frameRecycleCursor = 0; + dysonSphereLayer.SetFrameCapacity(64); + totalFrameSpInfo?.SetValue(dysonSphereLayer, 0); + } + dysonSphere.CheckAutoNodes(); + dysonSphere.PickAutoNode(); + dysonSphere.modelRenderer.RebuildModels(); + dysonSphere.needRecalculatePower = true; + }); + } +} diff --git a/CheatEnabler/Functions/DysonSphere/GeometryHelpers.cs b/CheatEnabler/Functions/DysonSphere/GeometryHelpers.cs new file mode 100644 index 0000000..ea170d0 --- /dev/null +++ b/CheatEnabler/Functions/DysonSphere/GeometryHelpers.cs @@ -0,0 +1,788 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using UnityEngine; +using UXAssist.Common; + +namespace CheatEnabler.Functions.DysonSphere; + +public static class GeometryHelpers +{ + 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); + public 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)} }, + ]; + + public 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 DysonNode QuickAddDysonNode(this DysonSphereLayer layer, int protoId, Vector3 pos) + { + int nodeId; + if (layer.nodeRecycleCursor > 0) + { + int[] array = layer.nodeRecycle; + int num = layer.nodeRecycleCursor - 1; + layer.nodeRecycleCursor = num; + nodeId = array[num]; + } + else + { + int nodePoolIndex = layer.nodeCursor; + layer.nodeCursor = nodePoolIndex + 1; + nodeId = nodePoolIndex; + if (nodeId == layer.nodeCapacity) + { + layer.SetNodeCapacity(layer.nodeCapacity * 2); + } + } + DysonNode node = null; + if (layer.nodePool[nodeId] == null) + { + node = new DysonNode(); + layer.nodePool[nodeId] = node; + } + else + { + node = layer.nodePool[nodeId]; + node.SetEmpty(); + } + node.id = nodeId; + node.protoId = protoId; + node.layerId = layer.id; + node.pos = pos; + node.reserved = false; + node.sp = 0; + node.spMax = DysonNode.kSpPerNode; + layer.dysonSphere.AddDysonNodeRData(node, true); + return node; + } + public static DysonFrame QuickAddDysonFrame(this DysonSphereLayer layer, int protoId, DysonNode nodeA, DysonNode nodeB, bool euler) + { + int newId; + if (layer.frameRecycleCursor > 0) + { + var array = layer.frameRecycle; + var index = layer.frameRecycleCursor - 1; + layer.frameRecycleCursor = index; + newId = array[index]; + } + else + { + var index = layer.frameCursor; + layer.frameCursor = index + 1; + newId = index; + if (newId == layer.frameCapacity) + { + layer.SetFrameCapacity(layer.frameCapacity * 2); + } + } + DysonFrame frame = layer.framePool[newId]; + if (frame == null) + { + frame = new DysonFrame(); + layer.framePool[newId] = frame; + } + else + { + frame = layer.framePool[newId]; + frame.SetEmpty(); + } + frame.id = newId; + frame.layerId = layer.id; + frame.protoId = protoId + DysonSphereSegmentRenderer.nodeProtoCount; + frame.reserved = false; + frame.nodeA = nodeA; + frame.nodeB = nodeB; + frame.euler = euler; + frame.spA = 0; + frame.spB = 0; + frame.spMax = frame.segCount * DysonFrame.kSpPerSeg; + nodeA.frames.Add(frame); + nodeB.frames.Add(frame); + return frame; + } + private static readonly ThreadLocal> _vmap = new(() => new(16384)); + public static int CalculateTriangleVertCount(Vector3[] pos) + { + 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++) + { + 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 = Math.Round(polygon[0].magnitude * 10.0) / 10.0; + for (int j = 0; j < polygon.Length; j++) + { + polygon[j] = polygon[j].normalized * radius; + } + var center = (sum / num).normalized * radius; + float num3 = 0f; + for (int k = 0; k < 3; k++) + { + float num4 = Vector3.Distance(center, polygon[k]); + if (num4 > num3) + { + num3 = num4; + } + } + var gridScale = (int)(Math.Pow(radius / 4000.0, 0.75) + 0.5); + gridScale = ((gridScale < 1) ? 1 : gridScale); + var gridSize = gridScale * 80f; + var gridSizeDouble = (double)gridSize; + var cpPerVertex = gridScale * gridScale * 2; + + 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 * 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++) + { + 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 = gridSizeDouble * 0.5; + for (int m = -num5; m <= num5; m++) + { + for (int n = -num5; n <= num5; n++) + { + if (m - n <= num5 && m - n >= -num5) + { + VectorLF3 vectorLF3; + 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++) + { + double num11 = -(polyn[num10].x * vectorLF3.x + polyn[num10].y * vectorLF3.y + polyn[num10].z * vectorLF3.z) / polynu[num10]; + 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 *= 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; + if (num12 < 0.0 || (num12 == 0.0 && vectorLF4.x == 0.0 && vectorLF4.y == 0.0 && vectorLF4.z == 0.0)) + { + num9++; + } + } + } + if ((num9 & 1) == 1) + { + int num13 = DysonShell._get_key(m, n); + vmap[num13] = vectorLF3; + } + else + { + for (int num14 = 0; num14 < 3; num14++) + { + VectorLF3 vectorLF6 = polygon[num14]; + VectorLF3 vectorLF7 = polyn[num14]; + VectorLF3 vectorLF8 = vectorLF3 - vectorLF6; + double num15 = vectorLF7.x * vectorLF8.x + vectorLF7.y * vectorLF8.y + vectorLF7.z * vectorLF8.z; + double num16 = Math.Abs(num15); + if (num16 <= num7) + { + VectorLF3 vectorLF9 = polygon[(num14 + 1) % 3]; + VectorLF3 vectorLF10 = vectorLF3 - vectorLF7 * num15; + VectorLF3 vectorLF11 = vectorLF9 - vectorLF6; + double magnitude = vectorLF11.magnitude; + VectorLF3 vectorLF12 = vectorLF11 / magnitude; + VectorLF3 vectorLF13 = vectorLF10 - vectorLF6; + double num17 = vectorLF12.x * vectorLF13.x + vectorLF12.y * vectorLF13.y + vectorLF12.z * vectorLF13.z; + double num18; + if (num17 < 0.0) + { + num18 = vectorLF8.magnitude; + } + else if (num17 > magnitude) + { + num18 = (vectorLF3 - vectorLF9).magnitude; + } + else + { + num18 = num16; + } + if (num18 <= num7) + { + int num19 = DysonShell._get_key(m, n); + vmap[num19] = vectorLF3; + break; + } + } + } + } + } + } + } + return vmap.Count; + } + public static bool MyGenerateGeometry(this DysonShell shell) + { + VectorLF3 sum = VectorLF3.zero; + double num = 0.0; + for (int i = 0; i < shell.frames.Count; i++) + { + 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 = 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; + } + var normalized = (sum / num).normalized; + shell.center = normalized * shell.radius; + float num3 = 0f; + for (int k = 0; k < shell.polygon.Count; k++) + { + float num4 = Vector3.Distance(shell.center, shell.polygon[k]); + if (num4 > num3) + { + num3 = num4; + } + } + shell.gridScale = (int)(Math.Pow(shell.radius / 4000.0, 0.75) + 0.5); + shell.gridScale = ((shell.gridScale < 1) ? 1 : shell.gridScale); + shell.gridSize = shell.gridScale * 80f; + var gridSizeDouble = (double)shell.gridSize; + shell.cpPerVertex = shell.gridScale * shell.gridScale * 2; + 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 * 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++) + { + 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 = gridSizeDouble * 0.5; + for (int m = -num5; m <= num5; m++) + { + for (int n = -num5; n <= num5; n++) + { + if (m - n <= num5 && m - n >= -num5) + { + VectorLF3 vectorLF3; + 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++) + { + double num11 = -(shell.polyn[num10].x * vectorLF3.x + shell.polyn[num10].y * vectorLF3.y + shell.polyn[num10].z * vectorLF3.z) / shell.polynu[num10]; + 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 *= 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; + if (num12 < 0.0 || (num12 == 0.0 && vectorLF4.x == 0.0 && vectorLF4.y == 0.0 && vectorLF4.z == 0.0)) + { + num9++; + } + } + } + if ((num9 & 1) == 1) + { + int num13 = DysonShell._get_key(m, n); + DysonShell.s_vmap[num13] = vectorLF3; + } + else + { + for (int num14 = 0; num14 < count; num14++) + { + VectorLF3 vectorLF6 = shell.polygon[num14]; + VectorLF3 vectorLF7 = shell.polyn[num14]; + VectorLF3 vectorLF8 = vectorLF3 - vectorLF6; + double num15 = vectorLF7.x * vectorLF8.x + vectorLF7.y * vectorLF8.y + vectorLF7.z * vectorLF8.z; + double num16 = Math.Abs(num15); + if (num16 <= num7) + { + VectorLF3 vectorLF9 = shell.polygon[(num14 + 1) % count]; + VectorLF3 vectorLF10 = vectorLF3 - vectorLF7 * num15; + VectorLF3 vectorLF11 = vectorLF9 - vectorLF6; + double magnitude = vectorLF11.magnitude; + VectorLF3 vectorLF12 = vectorLF11 / magnitude; + VectorLF3 vectorLF13 = vectorLF10 - vectorLF6; + double num17 = vectorLF12.x * vectorLF13.x + vectorLF12.y * vectorLF13.y + vectorLF12.z * vectorLF13.z; + double num18; + if (num17 < 0.0) + { + num18 = vectorLF8.magnitude; + } + else if (num17 > magnitude) + { + num18 = (vectorLF3 - vectorLF9).magnitude; + } + else + { + num18 = num16; + } + if (num18 <= num7) + { + int num19 = DysonShell._get_key(m, n); + DysonShell.s_vmap[num19] = vectorLF3; + DysonShell.s_outvmap[num19] = vectorLF3; + break; + } + } + } + } + } + } + } + int count2 = DysonShell.s_vmap.Count; + if (count2 > 32767) + { + return false; + } + shell.verts = new Vector3[count2]; + shell.uvs = new Vector2[count2]; + shell.uv2s = new Vector2[count2]; + shell.vkeys = new int[count2]; + shell._gen_points_topo_indices(count2); + shell.vAdjs = new short[count2 * 6]; + for (int num20 = 0; num20 < shell.vAdjs.Length; num20++) + { + shell.vAdjs[num20] = -1; + } + int num21 = 0; + foreach (KeyValuePair keyValuePair in DysonShell.s_vmap) + { + Vector3 value = keyValuePair.Value; + DysonShell.s_ivmap[keyValuePair.Key] = num21; + shell.verts[num21] = value; + shell.uv2s[num21].x = DysonShell.s_outvmap.ContainsKey(keyValuePair.Key) ? 0 : 1; + shell.vkeys[num21] = keyValuePair.Key; + num21++; + } + foreach (KeyValuePair keyValuePair2 in DysonShell.s_ivmap) + { + int key = keyValuePair2.Key; + int num22 = DysonShell.s_ivmap[key]; + int num23 = key + 65536; + int num24 = key - 1; + int num25 = key - 65537; + int num26 = key - 65536; + int num27 = key + 1; + int num28 = key + 65537; + bool flag = DysonShell.s_ivmap.ContainsKey(num23); + bool flag2 = DysonShell.s_ivmap.ContainsKey(num24); + bool flag3 = DysonShell.s_ivmap.ContainsKey(num25); + bool flag4 = DysonShell.s_ivmap.ContainsKey(num26); + bool flag5 = DysonShell.s_ivmap.ContainsKey(num27); + bool flag6 = DysonShell.s_ivmap.ContainsKey(num28); + shell.vAdjs[num22 * 6] = (short)(flag ? DysonShell.s_ivmap[num23] : (-1)); + shell.vAdjs[num22 * 6 + 1] = (short)(flag2 ? DysonShell.s_ivmap[num24] : (-1)); + shell.vAdjs[num22 * 6 + 2] = (short)(flag3 ? DysonShell.s_ivmap[num25] : (-1)); + shell.vAdjs[num22 * 6 + 3] = (short)(flag4 ? DysonShell.s_ivmap[num26] : (-1)); + shell.vAdjs[num22 * 6 + 4] = (short)(flag5 ? DysonShell.s_ivmap[num27] : (-1)); + shell.vAdjs[num22 * 6 + 5] = (short)(flag6 ? DysonShell.s_ivmap[num28] : (-1)); + } + int num29 = 0; + int num30 = 0; + for (int num31 = 0; num31 < count2; num31++) + { + double num32 = shell.radius * 2.0; + int num33 = -1; + VectorLF3 vectorLF14 = shell.verts[num31]; + for (int num34 = 0; num34 < count; num34++) + { + VectorLF3 vectorLF15 = shell.polygon[num34]; + VectorLF3 vectorLF16 = shell.polygon[(num34 + 1) % count]; + VectorLF3 vectorLF17 = shell.polyn[num34]; + VectorLF3 vectorLF18 = vectorLF14 - vectorLF15; + double num35 = vectorLF17.x * vectorLF18.x + vectorLF17.y * vectorLF18.y + vectorLF17.z * vectorLF18.z; + VectorLF3 vectorLF19 = vectorLF14 - vectorLF17 * num35; + VectorLF3 vectorLF20 = vectorLF14 - vectorLF16; + double num36 = vectorLF17.x * vectorLF20.x + vectorLF17.y * vectorLF20.y + vectorLF17.z * vectorLF20.z; + VectorLF3 vectorLF21 = vectorLF16 - vectorLF15; + double magnitude2 = vectorLF21.magnitude; + VectorLF3 vectorLF22 = vectorLF21 / magnitude2; + VectorLF3 vectorLF23 = vectorLF19 - vectorLF15; + double num37 = vectorLF22.x * vectorLF23.x + vectorLF22.y * vectorLF23.y + vectorLF22.z * vectorLF23.z; + double num38; + if (num37 < 0.0) + { + num38 = (vectorLF14 - vectorLF15).magnitude; + num38 -= Math.Abs(num35) * 0.001; + } + else if (num37 > magnitude2) + { + num38 = (vectorLF14 - vectorLF16).magnitude; + num38 -= Math.Abs(num36) * 0.001; + } + else + { + num38 = Math.Abs(num35); + num38 -= Math.Abs(num35) * 0.001; + } + if (num38 < num32) + { + num32 = num38; + num33 = num34; + } + } + 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]); + if (num39 > 0.1) + { + num29++; + } + else if (num39 < -0.1) + { + num30++; + } + } + } + if (num29 > num30) + { + shell.clockwise = true; + } + else + { + shell.clockwise = false; + } + shell.vertAttr = new int[count2]; + shell.vertsq = new short[count2]; + shell.vertsqOffset = new int[shell.nodes.Count + 1]; + int count3 = shell.nodes.Count; + int num40 = count3 / 2; + for (int num41 = 0; num41 < count2; num41++) + { + Vector3 vector3 = shell.verts[num41]; + double num42 = double.MaxValue; + int num43 = 0; + int num44 = 0; + int num45 = num41 + 479001600; + for (int num46 = 0; num46 < count3; num46++) + { + int num47 = num45 % count3 - num46; + if (num47 < 0) + { + num47 = -num47; + } + if (num47 > num40) + { + num47 = count3 - num47; + } + double num48 = (double)(vector3 - shell.nodes[num46].pos).sqrMagnitude; + num48 += num47; + if (num48 < num42) + { + num42 = num48; + num43 = shell.nodes[num46].id; + num44 = num46; + } + } + shell.vertAttr[num41] = num43; + shell.vertsqOffset[num44]++; + } + int num49 = 0; + for (int num50 = 0; num50 < shell.vertsqOffset.Length; num50++) + { + num49 += shell.vertsqOffset[num50]; + } + Assert.True(num49 == count2); + for (int num51 = shell.vertsqOffset.Length - 1; num51 >= 0; num51--) + { + shell.vertsqOffset[num51] = num49; + if (num51 > 0) + { + num49 -= shell.vertsqOffset[num51 - 1]; + } + } + Assert.Zero(num49); + shell._openListPrepare(); + int num52 = shell.randSeed; + int num53 = 0; + while (num53 < count3) + { + Vector3 pos = shell.nodes[num53].pos; + int num54 = shell.nodes[num53].id; + float num55 = float.MaxValue; + int num56 = -1; + for (int num57 = 0; num57 < count2; num57++) + { + if (shell.vertAttr[num57] == num54 && (shell.vAdjs[num57 * 6] >= 0 || shell.vAdjs[num57 * 6 + 1] >= 0 || shell.vAdjs[num57 * 6 + 2] >= 0 || shell.vAdjs[num57 * 6 + 3] >= 0 || shell.vAdjs[num57 * 6 + 4] >= 0 || shell.vAdjs[num57 * 6 + 5] >= 0)) + { + float sqrMagnitude = (shell.verts[num57] - pos).sqrMagnitude; + if (sqrMagnitude < num55) + { + num55 = sqrMagnitude; + num56 = num57; + } + } + } + if (num56 >= 0) + { + shell._openListAdd(num56); + } + int num58 = shell.vertsqOffset[num53]; + int num59 = shell.vertsqOffset[num53 + 1] - shell.vertsqOffset[num53]; + double num60 = 0.0; + for (; ; ) + { + int num61 = shell._traverseRandomVertex(shell.nodes[num53].id, ref num52); + if (num61 < 0) + { + break; + } + shell.vertsq[num58++] = (short)num61; + num60 += 1.0; + shell.uvs[num61].x = num53; + shell.uvs[num61].y = (float)(num60 / num59); + if (num58 == shell.vertsqOffset[num53 + 1]) + { + goto Block_57; + } + } + IL_1329: + if (num58 < shell.vertsqOffset[num53 + 1]) + { + for (int num62 = 0; num62 < count2; num62++) + { + if (shell.vertAttr[num62] == num54 && !shell._tmp_marked[num62]) + { + shell.vertsq[num58++] = (short)num62; + num60 += 1.0; + shell.uvs[num62].x = num53; + shell.uvs[num62].y = (float)(num60 / num59); + } + } + } + Assert.False(num58 > shell.vertsqOffset[num53 + 1]); + Assert.False(num58 < shell.vertsqOffset[num53 + 1]); + shell._openListClear(); + num53++; + continue; + Block_57: + Assert.Zero(shell._tmp_openCount); + goto IL_1329; + } + shell._openListFree(); + shell.vertexCount = count2; + return true; + } + public static int QuickAddDysonShell(this DysonSphereLayer layer, int protoId, DysonNode[] nodes, DysonFrame[] frames, bool limit) + { + int shellId = 0; + if (layer.shellRecycleCursor > 0) + { + int[] array = layer.shellRecycle; + int index = layer.shellRecycleCursor - 1; + layer.shellRecycleCursor = index; + shellId = array[index]; + } + else + { + int index = layer.shellCursor; + layer.shellCursor = index + 1; + shellId = index; + if (shellId == layer.shellCapacity) + { + layer.SetShellCapacity(layer.shellCapacity * 2); + } + } + var shell = layer.shellPool[shellId]; + if (shell == null) + { + shell = new DysonShell(layer); + layer.shellPool[shellId] = shell; + } + else + { + shell.SetEmpty(); + } + shell.id = shellId; + shell.layerId = layer.id; + shell.protoId = protoId; + shell.randSeed = layer.id * 10000 + shellId; + for (int j = 0; j < nodes.Length; j++) + { + DysonNode dysonNode = nodes[j]; + DysonFrame dysonFrame = frames[j]; + List segments = dysonFrame.GetSegments(); + if (dysonNode == dysonFrame.nodeA) + { + for (int k = 0; k < segments.Count - 1; k++) + { + shell.polygon.Add(segments[k]); + } + } + else + { + for (int l = segments.Count - 1; l >= 1; l--) + { + shell.polygon.Add(segments[l]); + } + } + shell.nodeIndexMap[dysonNode.id] = shell.nodes.Count; + shell.nodes.Add(dysonNode); + shell.frames.Add(dysonFrame); + } + if (!shell.MyGenerateGeometry() || (limit && DysonShell.s_vmap.Count < 32000)) + { + CheatEnabler.Logger.LogDebug($"Stripped VertCount: {DysonShell.s_vmap.Count}"); + shell.Free(); + layer.shellPool[shellId] = null; + int recycleIndex = layer.shellRecycleCursor; + layer.shellRecycleCursor = recycleIndex + 1; + layer.shellRecycle[recycleIndex] = shellId; + return 0; + } + // 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); + } + shell.GenerateModelObjects(); + return shellId; + } + public static void QuickRemoveDysonNode(this DysonSphereLayer layer, int nodeId) + { + var node = layer.nodePool[nodeId]; + if (node == null || node.id != nodeId) return; + var dysonSphere = layer.dysonSphere; + dysonSphere.swarm.OnNodeRemove(layer.id, nodeId); + dysonSphere.RemoveAutoNode(node); + dysonSphere.RemoveNodeRocket(node); + dysonSphere.RemoveDysonNodeRData(node); + node.Free(); + layer.nodePool[nodeId] = null; + int recycleIndex = layer.nodeRecycleCursor; + layer.nodeRecycleCursor = recycleIndex + 1; + layer.nodeRecycle[recycleIndex] = nodeId; + } + + public static void QuickRemoveDysonFrame(this DysonSphereLayer layer, int frameId) + { + var frame = layer.framePool[frameId]; + frame.nodeA.frames.Remove(frame); + frame.nodeB.frames.Remove(frame); + frame.Free(); + layer.framePool[frameId] = null; + int recycleIndex = layer.frameRecycleCursor; + layer.frameRecycleCursor = recycleIndex + 1; + layer.frameRecycle[recycleIndex] = frameId; + } + public static int AlignUpToPowerOfTwo(int value) + { + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + return value + 1; + } + public class SupposedShell + { + public Vector3 posA; + public Vector3 posB; + public Vector3 posC; + + public float area; + public int vertCount; + } +} diff --git a/CheatEnabler/Functions/DysonSphere/IllegalShellFunctions.cs b/CheatEnabler/Functions/DysonSphere/IllegalShellFunctions.cs new file mode 100644 index 0000000..96855f2 --- /dev/null +++ b/CheatEnabler/Functions/DysonSphere/IllegalShellFunctions.cs @@ -0,0 +1,623 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CheatEnabler.Functions; +using static CheatEnabler.Functions.DysonSphere.GeometryHelpers; +using UnityEngine; +using UXAssist.Common; +using UXAssist.Common.ModFeatures; + +namespace CheatEnabler.Functions.DysonSphere; + +[ModFeature("IllegalShellFunctions")] +public static class IllegalShellFunctions +{ + public static void DuplicateShellsWithHighestProduction() + { + var resolved = DysonSphereResolver.ResolveEditorOrLocalSphere(); + if (resolved == null) return; + var (dysonSphere, star) = resolved.Value; + DysonShell.s_vmap ??= new Dictionary(16384); + DysonShell.s_outvmap ??= new Dictionary(16384); + DysonShell.s_ivmap ??= new Dictionary(16384); + DysonSphereLayer layer = null; + var nodePos = new List(); + var isEuler = new List(); + DysonShell shell = null; + for (var i = 1; i < dysonSphere.layersIdBased.Length; i++) + { + layer = dysonSphere.layersIdBased[i]; + if (layer == null || layer.id != i) continue; + for (var j = 1; j < layer.shellCursor; j++) + { + shell = layer.shellPool[j]; + if (shell == null) continue; + if (shell.id != j) + { + shell = null; + continue; + } + nodePos.AddRange(shell.nodes.Select(node => node.pos)); + isEuler.AddRange(shell.frames.Select(frame => frame.euler)); + break; + } + if (nodePos.Count > 0) break; + } + if (nodePos.Count == 0) + { + UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null); + return; + } + var currentShellCount = layer.shellCount; + var keepCount = DysonSphereFunctions.ShellsCountForFunctions.Value; + if (currentShellCount >= keepCount) return; + CheatEnabler.Logger.LogDebug($"NodePositions: {nodePos[0]}, {nodePos[1]}, {nodePos[2]}"); + var nodeCount = nodePos.Count; + DysonNode[] nodes = [.. shell.nodes]; + DysonFrame[] frames = [.. shell.frames]; + if (frames.Length == 0) + { + isEuler = new List(nodeCount); + frames = new DysonFrame[nodeCount]; + for (var i = 0; i < nodeCount; i++) + { + isEuler.Add(false); + frames[i] = layer.QuickAddDysonFrame(0, nodes[i], nodes[(i + 1) % nodeCount], false); + } + } + var cpMax = new long[nodeCount]; + for (var i = 0; i < nodeCount; i++) + { + cpMax[i] = (shell.vertsqOffset[i + 1] - shell.vertsqOffset[i]) * shell.cpPerVertex; + } + long[] totalCpMax = [.. nodes.Select(node => node.totalCpMax)]; + var dirtyFrames = new HashSet(); + for (var i = currentShellCount; i < keepCount; i++) + { + dirtyFrames.Clear(); + for (var j = 0; j < nodeCount; j++) + { + totalCpMax[j] += cpMax[j]; + if (totalCpMax[j] > int.MaxValue) + { + totalCpMax[j] = cpMax[j]; + dirtyFrames.Add(j > 0 ? j - 1 : nodeCount - 1); + dirtyFrames.Add(j); + nodes[j] = layer.QuickAddDysonNode(0, nodePos[j]); + } + } + foreach (var frameId in dirtyFrames) + { + frames[frameId] = layer.QuickAddDysonFrame(0, nodes[frameId], nodes[(frameId + 1) % nodeCount], isEuler[frameId]); + } + 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(); + dysonSphere.inEditorRenderMaskS = 0; + dysonSphere.inEditorRenderMaskL = 0; + dysonSphere.inGameRenderMaskS = 0; + dysonSphere.inGameRenderMaskL = 0; + } + + public static void KeepMaxProductionShells() + { + var resolved = DysonSphereResolver.ResolveEditorOrLocalSphere(); + if (resolved == null) return; + var (dysonSphere, star) = resolved.Value; + int retainCount = DysonSphereFunctions.ShellsCountForFunctions.Value; + for (var i = 1; i < dysonSphere.layersIdBased.Length; i++) + { + var layer = dysonSphere.layersIdBased[i]; + if (layer == null || layer.id != i) continue; + var shells = layer.shellPool.Where(shell => shell != null).OrderByDescending(shell => shell.vertexCount).ToArray(); + if (shells.Length < 1) continue; + for (var j = retainCount; j < shells.Length; j++) + { + var shell = shells[j]; + var id = shell.id; + layer.shellPool[id] = null; + for (var k = 0; k < shell.nodes.Count; k++) + { + shell.nodes[k].shells.Remove(shell); + } + shell.Free(); + shells[j] = null; + } + var poolCapacity = GeometryHelpers.AlignUpToPowerOfTwo(retainCount + 1); + if (poolCapacity < 64) poolCapacity = 64; + layer.shellPool = new DysonShell[poolCapacity]; + layer.shellRecycle = new int[poolCapacity]; + layer.shellRecycleCursor = 0; + layer.shellCapacity = poolCapacity; + layer.shellCursor = retainCount + 1; + HashSet retainNodes = []; + HashSet<(int, int)> retainFrames = []; + for (var j = 0; j < retainCount; j++) + { + var shell = shells[j]; + retainNodes.UnionWith(shell.nodes.Select(node => node.id)); + int shellId = j + 1; + layer.shellPool[shellId] = shell; + shell.id = shellId; + for (var k = 0; k < shell.nodes.Count; k++) + { + var idA = shell.nodes[k].id; + var idB = shell.nodes[(k + 1) % shell.nodes.Count].id; + retainFrames.Add((idA, idB)); + retainFrames.Add((idB, idA)); + } + } + var nodes = layer.nodePool.Where(node => node != null && retainNodes.Contains(node.id)).ToArray(); + var frames = layer.framePool.Where(frame => frame != null && retainFrames.Contains((frame.nodeA.id, frame.nodeB.id))).ToArray(); + poolCapacity = GeometryHelpers.AlignUpToPowerOfTwo(frames.Length + 1); + if (poolCapacity < 64) poolCapacity = 64; + layer.framePool = new DysonFrame[poolCapacity]; + layer.frameRecycle = new int[poolCapacity]; + layer.frameRecycleCursor = 0; + layer.frameCapacity = poolCapacity; + layer.frameCursor = frames.Length + 1; + for (var j = 0; j < frames.Length; j++) + { + int id = j + 1; + layer.framePool[id] = frames[j]; + frames[j].id = id; + } + foreach (var node in nodes) + { + if (node != null && node.id > 0) + { + dysonSphere.RemoveDysonNodeRData(node); + } + } + poolCapacity = GeometryHelpers.AlignUpToPowerOfTwo(nodes.Length + 1); + if (poolCapacity < 64) poolCapacity = 64; + layer.nodePool = new DysonNode[poolCapacity]; + layer.nodeRecycle = new int[poolCapacity]; + layer.nodeRecycleCursor = 0; + layer.nodeCapacity = poolCapacity; + layer.nodeCursor = nodes.Length + 1; + for (var j = 0; j < nodes.Length; j++) + { + int id = j + 1; + layer.nodePool[id] = nodes[j]; + nodes[j].id = id; + } + for (var j = 1; j < layer.shellCursor; j++) + { + var shell = layer.shellPool[j]; + if (shell == null || shell.id != j) continue; + shell.nodeIndexMap.Clear(); + for (var k = 0; k < shell.nodes.Count; k++) + { + shell.nodeIndexMap[shell.nodes[k].id] = k; + } + } + for (var j = 1; j < layer.nodeCursor; j++) + { + var node = layer.nodePool[j]; + if (node == null || node.id != j) continue; + dysonSphere.AddDysonNodeRData(node, true); + node.RecalcSpReq(); + node.RecalcCpReq(); + } + } + dysonSphere.CheckAutoNodes(); + if (dysonSphere.autoNodeCount <= 0) + { + dysonSphere.PickAutoNode(); + } + dysonSphere.modelRenderer.RebuildModels(); + } + + public static void CreateIllegalDysonShellQuickly(int triangleCount) + { + var star = DysonSphereResolver.ResolveEditorOrLocalStar(); + if (star == 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(16384); + DysonShell.s_outvmap ??= new Dictionary(16384); + DysonShell.s_ivmap ??= new Dictionary(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 = GeometryHelpers.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(); + 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; + } + } + + private static bool CreateIllegalDysonShellWithMaxOutputForLayer(DysonSphereLayer layer) + { + DysonShell.s_vmap ??= new Dictionary(16384); + DysonShell.s_outvmap ??= new Dictionary(16384); + DysonShell.s_ivmap ??= new Dictionary(16384); + var shellsChanged = false; + var mutex = new object(); + var supposedShells = new List(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)) * layer.orbitRadius; + } + 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)); + CheatEnabler.Logger.LogDebug($"Finished Area Sort"); + var maxVertCount = -1; + var maxJ = -1; + var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount - 1 }; + + var gridScale = (int)(Math.Pow(layer.orbitRadius / 4000.0, 0.75) + 0.5); + gridScale = (gridScale < 1) ? 1 : gridScale; + var cpPerVertex = gridScale * gridScale * 2; + var barrier = 0x7FFFFFFF / cpPerVertex; + if (barrier > 32767) barrier = 32767; + var truncValue = barrier / 1000 * 1000; + CheatEnabler.Logger.LogDebug($"cpPerVertex: {cpPerVertex}, Barrier: {barrier}, TruncValue: {truncValue}"); + + Parallel.For(0, supposedShells.Count, options, (j, loopState) => + { + var sshell = supposedShells[j]; + var vertCount = GeometryHelpers.CalculateTriangleVertCount([sshell.posA, sshell.posB, sshell.posC]); + if (vertCount <= barrier) + { + lock (mutex) + { + if (loopState.ShouldExitCurrentIteration) return; + if (vertCount > maxVertCount) + { + maxVertCount = vertCount; + maxJ = j; + if (maxVertCount >= truncValue) + { + CheatEnabler.Logger.LogDebug($"!!STOP!! Triangle {j}[{sshell.posA:F2} {sshell.posB:F2} {sshell.posC:F2}] has {vertCount} vertices"); + loopState.Stop(); + return; + } + CheatEnabler.Logger.LogDebug($"Triangle {j}[{sshell.posA:F2} {sshell.posB:F2} {sshell.posC:F2}] has {vertCount} vertices"); + } + } + } + }); + if (maxJ >= 0) + { + 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; + var sshell = supposedShells[maxJ]; + DysonNode[] newNodes = [layer.QuickAddDysonNode(0, sshell.posA), layer.QuickAddDysonNode(0, sshell.posB), layer.QuickAddDysonNode(0, sshell.posC)]; + 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; + } + return shellsChanged; + } + + public static void CreateIllegalDysonShellWithMaxOutput() + { + var star = DysonSphereResolver.ResolveEditorOrLocalStar(); + if (star == 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; + } + var layer = dysonSphere.layersIdBased[1]; + if (layer != null) + { + dysonSphere.RemoveLayer(1); + } + var maxOrbitRadius = Patches.DysonSpherePatch.UnlockMaxOrbitRadiusEnabled.Value ? Patches.DysonSpherePatch.UnlockMaxOrbitRadiusValue.Value : dysonSphere.maxOrbitRadius; + layer = dysonSphere.AddLayerOnId(1, maxOrbitRadius, Quaternion.Euler(0f, 0f, 0f), Mathf.Sqrt(dysonSphere.gravity / maxOrbitRadius) / maxOrbitRadius * 57.2957802f); + if (layer == null) return; + + var shellsChanged = CreateIllegalDysonShellWithMaxOutputForLayer(layer); + + 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; + } + + public static void CreateIllegalDysonShellWithMaxOutput2() + { + var star = DysonSphereResolver.ResolveEditorOrLocalStar(); + if (star == 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; + } + var shellsChanged = false; + for (int i = dysonSphere.layersSorted.Length - 1; i >= 0; i--) + { + var layer = dysonSphere.layersSorted[i]; + if (layer == null) continue; + shellsChanged = CreateIllegalDysonShellWithMaxOutputForLayer(layer) || shellsChanged; + } + + 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; + } + + public static void CreateIllegalDysonShellsSpecially() + { + var lastGridScale = 0; + var radiusList = new List(); + 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.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(16384); + DysonShell.s_outvmap ??= new Dictionary(16384); + DysonShell.s_ivmap ??= new Dictionary(16384); + var shellsChanged = false; + var mutex = new object(); + + for (var idx = 1; idx <= 2; idx++) + { + Dictionary<(int, int), int> availableFrames = []; + HashSet 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(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 = GeometryHelpers.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 = GeometryHelpers.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; + } +} diff --git a/CheatEnabler/Functions/DysonSphere/ShellCompletionFunctions.cs b/CheatEnabler/Functions/DysonSphere/ShellCompletionFunctions.cs new file mode 100644 index 0000000..f621b7e --- /dev/null +++ b/CheatEnabler/Functions/DysonSphere/ShellCompletionFunctions.cs @@ -0,0 +1,133 @@ +using System; +using System.Linq; +using HarmonyLib; +using UnityEngine; +using UXAssist.Common; +using UXAssist.Common.ModFeatures; + +namespace CheatEnabler.Functions.DysonSphere; + +[ModFeature("ShellCompletionFunctions")] +public static class ShellCompletionFunctions +{ + public static void CompleteShellsInstantly() + { + var resolved = DysonSphereResolver.ResolveEditorOrLocalSphere(); + if (resolved == null) return; + var (dysonSphere, star) = resolved.Value; + + UIMessageBox.Show("CheatEnabler".Translate(), string.Format("This will complete all Dyson Sphere shells on \"{0}\". Are you sure?".Translate(), star.displayName), "取消".Translate(), "确定".Translate(), UIMessageBox.QUESTION, null, () => + { + var totalNodeSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalNodeSP"); + var totalFrameSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP"); + var totalCpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalCP"); + + var rocketCount = 0L; + var solarSailCount = 0L; + foreach (var dysonSphereLayer in dysonSphere.layersIdBased) + { + if (dysonSphereLayer == null) continue; + long totalNodeSp = 0; + long totalFrameSp = 0; + long totalCp = 0; + for (var i = dysonSphereLayer.frameCursor - 1; i >= 0; i--) + { + var dysonFrame = dysonSphereLayer.framePool[i]; + if (dysonFrame == null || dysonFrame.id != i) continue; + totalFrameSp += dysonFrame.spMax; + var spMax = dysonFrame.spMax / 2; + if (dysonFrame.spA < spMax) + { + rocketCount += spMax - dysonFrame.spA; + dysonFrame.spA = spMax; + dysonSphere.UpdateProgress(dysonFrame); + } + if (dysonFrame.spB < spMax) + { + rocketCount += spMax - dysonFrame.spB; + dysonFrame.spB = spMax; + dysonSphere.UpdateProgress(dysonFrame); + } + } + for (var i = dysonSphereLayer.nodeCursor - 1; i >= 0; i--) + { + var dysonNode = dysonSphereLayer.nodePool[i]; + if (dysonNode == null || dysonNode.id != i) continue; + dysonNode.spOrdered = 0; + dysonNode._spReq = 0; + totalNodeSp += dysonNode.spMax; + var diff = dysonNode.spMax - dysonNode.sp; + if (diff > 0) + { + rocketCount += diff; + dysonNode.sp = dysonNode.spMax; + dysonSphere.UpdateProgress(dysonNode); + } + dysonNode._cpReq = 0; + dysonNode.cpOrdered = 0; + foreach (var shell in dysonNode.shells) + { + var nodeIndex = shell.nodeIndexMap[dysonNode.id]; + var cpMax = (shell.vertsqOffset[nodeIndex + 1] - shell.vertsqOffset[nodeIndex]) * shell.cpPerVertex; + totalCp += cpMax; + diff = cpMax - shell.nodecps[nodeIndex]; + shell.nodecps[nodeIndex] = cpMax; + shell.nodecps[shell.nodecps.Length - 1] += diff; + solarSailCount += diff; + if (totalCpInfo != null) + { + shell.SetMaterialDynamicVars(); + } + } + } + + totalNodeSpInfo?.SetValue(dysonSphereLayer, totalNodeSp); + totalFrameSpInfo?.SetValue(dysonSphereLayer, totalFrameSp); + totalCpInfo?.SetValue(dysonSphereLayer, totalCp); + } + dysonSphere.CheckAutoNodes(); + + var productRegister = dysonSphere.productRegister; + if (productRegister != null) + { + lock (productRegister) + { + var count = rocketCount; + while (count > 0x40000000L) + { + productRegister[ProductionStatistics.DYSON_STRUCTURE_ID] += 0x40000000; + count -= 0x40000000; + } + if (count > 0L) productRegister[ProductionStatistics.DYSON_STRUCTURE_ID] += (int)count; + count = solarSailCount; + while (count > 0x40000000L) + { + productRegister[ProductionStatistics.SOLAR_SAIL_ID] += 0x40000000; + productRegister[ProductionStatistics.DYSON_CELL_ID] += 0x40000000; + count -= 0x40000000; + } + if (count > 0L) + { + productRegister[ProductionStatistics.SOLAR_SAIL_ID] += (int)count; + productRegister[ProductionStatistics.DYSON_CELL_ID] += (int)count; + } + } + } + var consumeRegister = dysonSphere.consumeRegister; + if (consumeRegister != null) + { + lock (consumeRegister) + { + var count = solarSailCount; + while (count > 0x40000000L) + { + consumeRegister[ProductionStatistics.SOLAR_SAIL_ID] += 0x40000000; + count -= 0x40000000; + } + if (count > 0L) consumeRegister[ProductionStatistics.SOLAR_SAIL_ID] += (int)count; + } + } + dysonSphere.needRecalculatePower = true; + }); + } +} diff --git a/CheatEnabler/Functions/DysonSphereFunctions.cs b/CheatEnabler/Functions/DysonSphereFunctions.cs index 683b639..ba69d06 100644 --- a/CheatEnabler/Functions/DysonSphereFunctions.cs +++ b/CheatEnabler/Functions/DysonSphereFunctions.cs @@ -1,79 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using BepInEx.Configuration; -using HarmonyLib; -using UnityEngine; +using CheatEnabler.Functions.DysonSphere; using UXAssist.Common; using UXAssist.Common.ModFeatures; namespace CheatEnabler.Functions; -[ModFeature("DysonSphereFunctions")] +[ModFeature("CheatDysonSphere", Order = 20)] public static class DysonSphereFunctions { public static ConfigEntry IllegalDysonShellFunctionsEnabled; public static ConfigEntry 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.", "你不在任何星系中"); @@ -84,1619 +21,12 @@ public static class DysonSphereFunctions I18N.Add("No precalculated shell found for radius {0}.", "No precalculated shell found for radius {0}.", "没有找到适合半径 {0} 的预计算壳面"); } - public static void CompleteShellsInstantly() - { - 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 || dysonSphere.layerCount == 0) - { - UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null); - return; - } - - UIMessageBox.Show("CheatEnabler".Translate(), string.Format("This will complete all Dyson Sphere shells on \"{0}\" instantly. Are you sure?".Translate(), star.displayName), "取消".Translate(), "确定".Translate(), UIMessageBox.QUESTION, null, () => - { - var totalNodeSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalNodeSP"); - var totalFrameSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP"); - var totalCpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalCP"); - - var rocketCount = 0L; - var solarSailCount = 0L; - foreach (var dysonSphereLayer in dysonSphere.layersIdBased) - { - if (dysonSphereLayer == null) continue; - long totalNodeSp = 0; - long totalFrameSp = 0; - long totalCp = 0; - for (var i = dysonSphereLayer.frameCursor - 1; i >= 0; i--) - { - var dysonFrame = dysonSphereLayer.framePool[i]; - if (dysonFrame == null || dysonFrame.id != i) continue; - totalFrameSp += dysonFrame.spMax; - var spMax = dysonFrame.spMax / 2; - if (dysonFrame.spA < spMax) - { - rocketCount += spMax - dysonFrame.spA; - dysonFrame.spA = spMax; - dysonSphere.UpdateProgress(dysonFrame); - } - if (dysonFrame.spB < spMax) - { - rocketCount += spMax - dysonFrame.spB; - dysonFrame.spB = spMax; - dysonSphere.UpdateProgress(dysonFrame); - } - } - for (var i = dysonSphereLayer.nodeCursor - 1; i >= 0; i--) - { - var dysonNode = dysonSphereLayer.nodePool[i]; - if (dysonNode == null || dysonNode.id != i) continue; - dysonNode.spOrdered = 0; - dysonNode._spReq = 0; - totalNodeSp += dysonNode.spMax; - var diff = dysonNode.spMax - dysonNode.sp; - if (diff > 0) - { - rocketCount += diff; - dysonNode.sp = dysonNode.spMax; - dysonSphere.UpdateProgress(dysonNode); - } - dysonNode._cpReq = 0; - dysonNode.cpOrdered = 0; - foreach (var shell in dysonNode.shells) - { - var nodeIndex = shell.nodeIndexMap[dysonNode.id]; - var cpMax = (shell.vertsqOffset[nodeIndex + 1] - shell.vertsqOffset[nodeIndex]) * shell.cpPerVertex; - totalCp += cpMax; - diff = cpMax - shell.nodecps[nodeIndex]; - shell.nodecps[nodeIndex] = cpMax; - shell.nodecps[shell.nodecps.Length - 1] += diff; - solarSailCount += diff; - if (totalCpInfo != null) - { - shell.SetMaterialDynamicVars(); - } - } - } - - totalNodeSpInfo?.SetValue(dysonSphereLayer, totalNodeSp); - totalFrameSpInfo?.SetValue(dysonSphereLayer, totalFrameSp); - totalCpInfo?.SetValue(dysonSphereLayer, totalCp); - } - dysonSphere.CheckAutoNodes(); - - var productRegister = dysonSphere.productRegister; - if (productRegister != null) - { - lock (productRegister) - { - var count = rocketCount; - while (count > 0x40000000L) - { - productRegister[ProductionStatistics.DYSON_STRUCTURE_ID] += 0x40000000; - count -= 0x40000000; - } - if (count > 0L) productRegister[ProductionStatistics.DYSON_STRUCTURE_ID] += (int)count; - count = solarSailCount; - while (count > 0x40000000L) - { - productRegister[ProductionStatistics.SOLAR_SAIL_ID] += 0x40000000; - productRegister[ProductionStatistics.DYSON_CELL_ID] += 0x40000000; - count -= 0x40000000; - } - if (count > 0L) - { - productRegister[ProductionStatistics.SOLAR_SAIL_ID] += (int)count; - productRegister[ProductionStatistics.DYSON_CELL_ID] += (int)count; - } - } - } - var consumeRegister = dysonSphere.consumeRegister; - if (consumeRegister != null) - { - lock (consumeRegister) - { - var count = solarSailCount; - while (count > 0x40000000L) - { - consumeRegister[ProductionStatistics.SOLAR_SAIL_ID] += 0x40000000; - count -= 0x40000000; - } - if (count > 0L) consumeRegister[ProductionStatistics.SOLAR_SAIL_ID] += (int)count; - } - } - dysonSphere.needRecalculatePower = true; - }); - } - - public static void RemoveAllFrames() - { - 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 || dysonSphere.layerCount == 0) - { - UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null); - return; - } - - UIMessageBox.Show("CheatEnabler".Translate(), string.Format("This will remove all frames on \"{0}\". Are you sure?".Translate(), star.displayName), "取消".Translate(), "确定".Translate(), UIMessageBox.QUESTION, null, () => - { - var totalFrameSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP"); - - foreach (var dysonSphereLayer in dysonSphere.layersIdBased) - { - if (dysonSphereLayer == null) continue; - for (var i = dysonSphereLayer.nodeCursor - 1; i >= 0; i--) - { - var dysonNode = dysonSphereLayer.nodePool[i]; - if (dysonNode == null || dysonNode.id != i) continue; - if (dysonNode.frames.Count > 0) - dysonNode.frames.Clear(); - dysonNode.RecalcSpReq(); - } - for (var i = dysonSphereLayer.shellCursor - 1; i >= 0; i--) - { - var dysonShell = dysonSphereLayer.shellPool[i]; - if (dysonShell == null || dysonShell.id != i) continue; - if (dysonShell.frames.Count > 0) - dysonShell.frames.Clear(); - } - for (var i = dysonSphereLayer.frameCursor - 1; i >= 0; i--) - { - var dysonFrame = dysonSphereLayer.framePool[i]; - if (dysonFrame == null || dysonFrame.id != i) continue; - dysonFrame.Free(); - dysonSphereLayer.framePool[i] = null; - } - dysonSphereLayer.frameCursor = 1; - dysonSphereLayer.frameRecycleCursor = 0; - dysonSphereLayer.SetFrameCapacity(64); - totalFrameSpInfo?.SetValue(dysonSphereLayer, 0); - } - dysonSphere.CheckAutoNodes(); - dysonSphere.PickAutoNode(); - dysonSphere.modelRenderer.RebuildModels(); - dysonSphere.needRecalculatePower = true; - }); - } - - private static DysonNode QuickAddDysonNode(this DysonSphereLayer layer, int protoId, Vector3 pos) - { - int nodeId; - if (layer.nodeRecycleCursor > 0) - { - int[] array = layer.nodeRecycle; - int num = layer.nodeRecycleCursor - 1; - layer.nodeRecycleCursor = num; - nodeId = array[num]; - } - else - { - int nodePoolIndex = layer.nodeCursor; - layer.nodeCursor = nodePoolIndex + 1; - nodeId = nodePoolIndex; - if (nodeId == layer.nodeCapacity) - { - layer.SetNodeCapacity(layer.nodeCapacity * 2); - } - } - DysonNode node = null; - if (layer.nodePool[nodeId] == null) - { - node = new DysonNode(); - layer.nodePool[nodeId] = node; - } - else - { - node = layer.nodePool[nodeId]; - node.SetEmpty(); - } - node.id = nodeId; - node.protoId = protoId; - node.layerId = layer.id; - node.pos = pos; - node.reserved = false; - node.sp = 0; - node.spMax = DysonNode.kSpPerNode; - layer.dysonSphere.AddDysonNodeRData(node, true); - return node; - } - - private static DysonFrame QuickAddDysonFrame(this DysonSphereLayer layer, int protoId, DysonNode nodeA, DysonNode nodeB, bool euler) - { - int newId; - if (layer.frameRecycleCursor > 0) - { - var array = layer.frameRecycle; - var index = layer.frameRecycleCursor - 1; - layer.frameRecycleCursor = index; - newId = array[index]; - } - else - { - var index = layer.frameCursor; - layer.frameCursor = index + 1; - newId = index; - if (newId == layer.frameCapacity) - { - layer.SetFrameCapacity(layer.frameCapacity * 2); - } - } - DysonFrame frame = layer.framePool[newId]; - if (frame == null) - { - frame = new DysonFrame(); - layer.framePool[newId] = frame; - } - else - { - frame = layer.framePool[newId]; - frame.SetEmpty(); - } - frame.id = newId; - frame.layerId = layer.id; - frame.protoId = protoId + DysonSphereSegmentRenderer.nodeProtoCount; - frame.reserved = false; - frame.nodeA = nodeA; - frame.nodeB = nodeB; - frame.euler = euler; - frame.spA = 0; - frame.spB = 0; - frame.spMax = frame.segCount * DysonFrame.kSpPerSeg; - nodeA.frames.Add(frame); - nodeB.frames.Add(frame); - return frame; - } - - private static readonly ThreadLocal> _vmap = new(() => new(16384)); - private static int CalculateTriangleVertCount(Vector3[] pos) - { - 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++) - { - 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 = Math.Round(polygon[0].magnitude * 10.0) / 10.0; - for (int j = 0; j < polygon.Length; j++) - { - polygon[j] = polygon[j].normalized * radius; - } - var center = (sum / num).normalized * radius; - float num3 = 0f; - for (int k = 0; k < 3; k++) - { - float num4 = Vector3.Distance(center, polygon[k]); - if (num4 > num3) - { - num3 = num4; - } - } - var gridScale = (int)(Math.Pow(radius / 4000.0, 0.75) + 0.5); - gridScale = ((gridScale < 1) ? 1 : gridScale); - var gridSize = gridScale * 80f; - var gridSizeDouble = (double)gridSize; - var cpPerVertex = gridScale * gridScale * 2; - - 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 * 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++) - { - 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 = gridSizeDouble * 0.5; - for (int m = -num5; m <= num5; m++) - { - for (int n = -num5; n <= num5; n++) - { - if (m - n <= num5 && m - n >= -num5) - { - VectorLF3 vectorLF3; - 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++) - { - double num11 = -(polyn[num10].x * vectorLF3.x + polyn[num10].y * vectorLF3.y + polyn[num10].z * vectorLF3.z) / polynu[num10]; - 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 *= 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; - if (num12 < 0.0 || (num12 == 0.0 && vectorLF4.x == 0.0 && vectorLF4.y == 0.0 && vectorLF4.z == 0.0)) - { - num9++; - } - } - } - if ((num9 & 1) == 1) - { - int num13 = DysonShell._get_key(m, n); - vmap[num13] = vectorLF3; - } - else - { - for (int num14 = 0; num14 < 3; num14++) - { - VectorLF3 vectorLF6 = polygon[num14]; - VectorLF3 vectorLF7 = polyn[num14]; - VectorLF3 vectorLF8 = vectorLF3 - vectorLF6; - double num15 = vectorLF7.x * vectorLF8.x + vectorLF7.y * vectorLF8.y + vectorLF7.z * vectorLF8.z; - double num16 = Math.Abs(num15); - if (num16 <= num7) - { - VectorLF3 vectorLF9 = polygon[(num14 + 1) % 3]; - VectorLF3 vectorLF10 = vectorLF3 - vectorLF7 * num15; - VectorLF3 vectorLF11 = vectorLF9 - vectorLF6; - double magnitude = vectorLF11.magnitude; - VectorLF3 vectorLF12 = vectorLF11 / magnitude; - VectorLF3 vectorLF13 = vectorLF10 - vectorLF6; - double num17 = vectorLF12.x * vectorLF13.x + vectorLF12.y * vectorLF13.y + vectorLF12.z * vectorLF13.z; - double num18; - if (num17 < 0.0) - { - num18 = vectorLF8.magnitude; - } - else if (num17 > magnitude) - { - num18 = (vectorLF3 - vectorLF9).magnitude; - } - else - { - num18 = num16; - } - if (num18 <= num7) - { - int num19 = DysonShell._get_key(m, n); - vmap[num19] = vectorLF3; - break; - } - } - } - } - } - } - } - return vmap.Count; - } - - private static bool MyGenerateGeometry(this DysonShell shell) - { - VectorLF3 sum = VectorLF3.zero; - double num = 0.0; - for (int i = 0; i < shell.frames.Count; i++) - { - 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 = 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; - } - var normalized = (sum / num).normalized; - shell.center = normalized * shell.radius; - float num3 = 0f; - for (int k = 0; k < shell.polygon.Count; k++) - { - float num4 = Vector3.Distance(shell.center, shell.polygon[k]); - if (num4 > num3) - { - num3 = num4; - } - } - shell.gridScale = (int)(Math.Pow(shell.radius / 4000.0, 0.75) + 0.5); - shell.gridScale = ((shell.gridScale < 1) ? 1 : shell.gridScale); - shell.gridSize = shell.gridScale * 80f; - var gridSizeDouble = (double)shell.gridSize; - shell.cpPerVertex = shell.gridScale * shell.gridScale * 2; - 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 * 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++) - { - 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 = gridSizeDouble * 0.5; - for (int m = -num5; m <= num5; m++) - { - for (int n = -num5; n <= num5; n++) - { - if (m - n <= num5 && m - n >= -num5) - { - VectorLF3 vectorLF3; - 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++) - { - double num11 = -(shell.polyn[num10].x * vectorLF3.x + shell.polyn[num10].y * vectorLF3.y + shell.polyn[num10].z * vectorLF3.z) / shell.polynu[num10]; - 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 *= 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; - if (num12 < 0.0 || (num12 == 0.0 && vectorLF4.x == 0.0 && vectorLF4.y == 0.0 && vectorLF4.z == 0.0)) - { - num9++; - } - } - } - if ((num9 & 1) == 1) - { - int num13 = DysonShell._get_key(m, n); - DysonShell.s_vmap[num13] = vectorLF3; - } - else - { - for (int num14 = 0; num14 < count; num14++) - { - VectorLF3 vectorLF6 = shell.polygon[num14]; - VectorLF3 vectorLF7 = shell.polyn[num14]; - VectorLF3 vectorLF8 = vectorLF3 - vectorLF6; - double num15 = vectorLF7.x * vectorLF8.x + vectorLF7.y * vectorLF8.y + vectorLF7.z * vectorLF8.z; - double num16 = Math.Abs(num15); - if (num16 <= num7) - { - VectorLF3 vectorLF9 = shell.polygon[(num14 + 1) % count]; - VectorLF3 vectorLF10 = vectorLF3 - vectorLF7 * num15; - VectorLF3 vectorLF11 = vectorLF9 - vectorLF6; - double magnitude = vectorLF11.magnitude; - VectorLF3 vectorLF12 = vectorLF11 / magnitude; - VectorLF3 vectorLF13 = vectorLF10 - vectorLF6; - double num17 = vectorLF12.x * vectorLF13.x + vectorLF12.y * vectorLF13.y + vectorLF12.z * vectorLF13.z; - double num18; - if (num17 < 0.0) - { - num18 = vectorLF8.magnitude; - } - else if (num17 > magnitude) - { - num18 = (vectorLF3 - vectorLF9).magnitude; - } - else - { - num18 = num16; - } - if (num18 <= num7) - { - int num19 = DysonShell._get_key(m, n); - DysonShell.s_vmap[num19] = vectorLF3; - DysonShell.s_outvmap[num19] = vectorLF3; - break; - } - } - } - } - } - } - } - int count2 = DysonShell.s_vmap.Count; - if (count2 > 32767) - { - return false; - } - shell.verts = new Vector3[count2]; - shell.uvs = new Vector2[count2]; - shell.uv2s = new Vector2[count2]; - shell.vkeys = new int[count2]; - shell._gen_points_topo_indices(count2); - shell.vAdjs = new short[count2 * 6]; - for (int num20 = 0; num20 < shell.vAdjs.Length; num20++) - { - shell.vAdjs[num20] = -1; - } - int num21 = 0; - foreach (KeyValuePair keyValuePair in DysonShell.s_vmap) - { - Vector3 value = keyValuePair.Value; - DysonShell.s_ivmap[keyValuePair.Key] = num21; - shell.verts[num21] = value; - shell.uv2s[num21].x = DysonShell.s_outvmap.ContainsKey(keyValuePair.Key) ? 0 : 1; - shell.vkeys[num21] = keyValuePair.Key; - num21++; - } - foreach (KeyValuePair keyValuePair2 in DysonShell.s_ivmap) - { - int key = keyValuePair2.Key; - int num22 = DysonShell.s_ivmap[key]; - int num23 = key + 65536; - int num24 = key - 1; - int num25 = key - 65537; - int num26 = key - 65536; - int num27 = key + 1; - int num28 = key + 65537; - bool flag = DysonShell.s_ivmap.ContainsKey(num23); - bool flag2 = DysonShell.s_ivmap.ContainsKey(num24); - bool flag3 = DysonShell.s_ivmap.ContainsKey(num25); - bool flag4 = DysonShell.s_ivmap.ContainsKey(num26); - bool flag5 = DysonShell.s_ivmap.ContainsKey(num27); - bool flag6 = DysonShell.s_ivmap.ContainsKey(num28); - shell.vAdjs[num22 * 6] = (short)(flag ? DysonShell.s_ivmap[num23] : (-1)); - shell.vAdjs[num22 * 6 + 1] = (short)(flag2 ? DysonShell.s_ivmap[num24] : (-1)); - shell.vAdjs[num22 * 6 + 2] = (short)(flag3 ? DysonShell.s_ivmap[num25] : (-1)); - shell.vAdjs[num22 * 6 + 3] = (short)(flag4 ? DysonShell.s_ivmap[num26] : (-1)); - shell.vAdjs[num22 * 6 + 4] = (short)(flag5 ? DysonShell.s_ivmap[num27] : (-1)); - shell.vAdjs[num22 * 6 + 5] = (short)(flag6 ? DysonShell.s_ivmap[num28] : (-1)); - } - int num29 = 0; - int num30 = 0; - for (int num31 = 0; num31 < count2; num31++) - { - double num32 = shell.radius * 2.0; - int num33 = -1; - VectorLF3 vectorLF14 = shell.verts[num31]; - for (int num34 = 0; num34 < count; num34++) - { - VectorLF3 vectorLF15 = shell.polygon[num34]; - VectorLF3 vectorLF16 = shell.polygon[(num34 + 1) % count]; - VectorLF3 vectorLF17 = shell.polyn[num34]; - VectorLF3 vectorLF18 = vectorLF14 - vectorLF15; - double num35 = vectorLF17.x * vectorLF18.x + vectorLF17.y * vectorLF18.y + vectorLF17.z * vectorLF18.z; - VectorLF3 vectorLF19 = vectorLF14 - vectorLF17 * num35; - VectorLF3 vectorLF20 = vectorLF14 - vectorLF16; - double num36 = vectorLF17.x * vectorLF20.x + vectorLF17.y * vectorLF20.y + vectorLF17.z * vectorLF20.z; - VectorLF3 vectorLF21 = vectorLF16 - vectorLF15; - double magnitude2 = vectorLF21.magnitude; - VectorLF3 vectorLF22 = vectorLF21 / magnitude2; - VectorLF3 vectorLF23 = vectorLF19 - vectorLF15; - double num37 = vectorLF22.x * vectorLF23.x + vectorLF22.y * vectorLF23.y + vectorLF22.z * vectorLF23.z; - double num38; - if (num37 < 0.0) - { - num38 = (vectorLF14 - vectorLF15).magnitude; - num38 -= Math.Abs(num35) * 0.001; - } - else if (num37 > magnitude2) - { - num38 = (vectorLF14 - vectorLF16).magnitude; - num38 -= Math.Abs(num36) * 0.001; - } - else - { - num38 = Math.Abs(num35); - num38 -= Math.Abs(num35) * 0.001; - } - if (num38 < num32) - { - num32 = num38; - num33 = num34; - } - } - 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]); - if (num39 > 0.1) - { - num29++; - } - else if (num39 < -0.1) - { - num30++; - } - } - } - if (num29 > num30) - { - shell.clockwise = true; - } - else - { - shell.clockwise = false; - } - shell.vertAttr = new int[count2]; - shell.vertsq = new short[count2]; - shell.vertsqOffset = new int[shell.nodes.Count + 1]; - int count3 = shell.nodes.Count; - int num40 = count3 / 2; - for (int num41 = 0; num41 < count2; num41++) - { - Vector3 vector3 = shell.verts[num41]; - double num42 = double.MaxValue; - int num43 = 0; - int num44 = 0; - int num45 = num41 + 479001600; - for (int num46 = 0; num46 < count3; num46++) - { - int num47 = num45 % count3 - num46; - if (num47 < 0) - { - num47 = -num47; - } - if (num47 > num40) - { - num47 = count3 - num47; - } - double num48 = (double)(vector3 - shell.nodes[num46].pos).sqrMagnitude; - num48 += num47; - if (num48 < num42) - { - num42 = num48; - num43 = shell.nodes[num46].id; - num44 = num46; - } - } - shell.vertAttr[num41] = num43; - shell.vertsqOffset[num44]++; - } - int num49 = 0; - for (int num50 = 0; num50 < shell.vertsqOffset.Length; num50++) - { - num49 += shell.vertsqOffset[num50]; - } - Assert.True(num49 == count2); - for (int num51 = shell.vertsqOffset.Length - 1; num51 >= 0; num51--) - { - shell.vertsqOffset[num51] = num49; - if (num51 > 0) - { - num49 -= shell.vertsqOffset[num51 - 1]; - } - } - Assert.Zero(num49); - shell._openListPrepare(); - int num52 = shell.randSeed; - int num53 = 0; - while (num53 < count3) - { - Vector3 pos = shell.nodes[num53].pos; - int num54 = shell.nodes[num53].id; - float num55 = float.MaxValue; - int num56 = -1; - for (int num57 = 0; num57 < count2; num57++) - { - if (shell.vertAttr[num57] == num54 && (shell.vAdjs[num57 * 6] >= 0 || shell.vAdjs[num57 * 6 + 1] >= 0 || shell.vAdjs[num57 * 6 + 2] >= 0 || shell.vAdjs[num57 * 6 + 3] >= 0 || shell.vAdjs[num57 * 6 + 4] >= 0 || shell.vAdjs[num57 * 6 + 5] >= 0)) - { - float sqrMagnitude = (shell.verts[num57] - pos).sqrMagnitude; - if (sqrMagnitude < num55) - { - num55 = sqrMagnitude; - num56 = num57; - } - } - } - if (num56 >= 0) - { - shell._openListAdd(num56); - } - int num58 = shell.vertsqOffset[num53]; - int num59 = shell.vertsqOffset[num53 + 1] - shell.vertsqOffset[num53]; - double num60 = 0.0; - for (; ; ) - { - int num61 = shell._traverseRandomVertex(shell.nodes[num53].id, ref num52); - if (num61 < 0) - { - break; - } - shell.vertsq[num58++] = (short)num61; - num60 += 1.0; - shell.uvs[num61].x = num53; - shell.uvs[num61].y = (float)(num60 / num59); - if (num58 == shell.vertsqOffset[num53 + 1]) - { - goto Block_57; - } - } - IL_1329: - if (num58 < shell.vertsqOffset[num53 + 1]) - { - for (int num62 = 0; num62 < count2; num62++) - { - if (shell.vertAttr[num62] == num54 && !shell._tmp_marked[num62]) - { - shell.vertsq[num58++] = (short)num62; - num60 += 1.0; - shell.uvs[num62].x = num53; - shell.uvs[num62].y = (float)(num60 / num59); - } - } - } - Assert.False(num58 > shell.vertsqOffset[num53 + 1]); - Assert.False(num58 < shell.vertsqOffset[num53 + 1]); - shell._openListClear(); - num53++; - continue; - Block_57: - Assert.Zero(shell._tmp_openCount); - goto IL_1329; - } - shell._openListFree(); - shell.vertexCount = count2; - return true; - } - - private static int QuickAddDysonShell(this DysonSphereLayer layer, int protoId, DysonNode[] nodes, DysonFrame[] frames, bool limit) - { - int shellId = 0; - if (layer.shellRecycleCursor > 0) - { - int[] array = layer.shellRecycle; - int index = layer.shellRecycleCursor - 1; - layer.shellRecycleCursor = index; - shellId = array[index]; - } - else - { - int index = layer.shellCursor; - layer.shellCursor = index + 1; - shellId = index; - if (shellId == layer.shellCapacity) - { - layer.SetShellCapacity(layer.shellCapacity * 2); - } - } - var shell = layer.shellPool[shellId]; - if (shell == null) - { - shell = new DysonShell(layer); - layer.shellPool[shellId] = shell; - } - else - { - shell.SetEmpty(); - } - shell.id = shellId; - shell.layerId = layer.id; - shell.protoId = protoId; - shell.randSeed = layer.id * 10000 + shellId; - for (int j = 0; j < nodes.Length; j++) - { - DysonNode dysonNode = nodes[j]; - DysonFrame dysonFrame = frames[j]; - List segments = dysonFrame.GetSegments(); - if (dysonNode == dysonFrame.nodeA) - { - for (int k = 0; k < segments.Count - 1; k++) - { - shell.polygon.Add(segments[k]); - } - } - else - { - for (int l = segments.Count - 1; l >= 1; l--) - { - shell.polygon.Add(segments[l]); - } - } - shell.nodeIndexMap[dysonNode.id] = shell.nodes.Count; - shell.nodes.Add(dysonNode); - shell.frames.Add(dysonFrame); - } - if (!shell.MyGenerateGeometry() || (limit && DysonShell.s_vmap.Count < 32000)) - { - CheatEnabler.Logger.LogDebug($"Stripped VertCount: {DysonShell.s_vmap.Count}"); - shell.Free(); - layer.shellPool[shellId] = null; - int recycleIndex = layer.shellRecycleCursor; - layer.shellRecycleCursor = recycleIndex + 1; - layer.shellRecycle[recycleIndex] = shellId; - return 0; - } - // 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); - } - shell.GenerateModelObjects(); - return shellId; - } - - private static void QuickRemoveDysonNode(this DysonSphereLayer layer, int nodeId) - { - var node = layer.nodePool[nodeId]; - if (node == null || node.id != nodeId) return; - var dysonSphere = layer.dysonSphere; - dysonSphere.swarm.OnNodeRemove(layer.id, nodeId); - dysonSphere.RemoveAutoNode(node); - dysonSphere.RemoveNodeRocket(node); - dysonSphere.RemoveDysonNodeRData(node); - node.Free(); - layer.nodePool[nodeId] = null; - int recycleIndex = layer.nodeRecycleCursor; - layer.nodeRecycleCursor = recycleIndex + 1; - layer.nodeRecycle[recycleIndex] = nodeId; - } - - private static void QuickRemoveDysonFrame(this DysonSphereLayer layer, int frameId) - { - var frame = layer.framePool[frameId]; - frame.nodeA.frames.Remove(frame); - frame.nodeB.frames.Remove(frame); - frame.Free(); - layer.framePool[frameId] = null; - int recycleIndex = layer.frameRecycleCursor; - layer.frameRecycleCursor = recycleIndex + 1; - layer.frameRecycle[recycleIndex] = frameId; - } - - public static void DuplicateShellsWithHighestProduction() - { - 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 || dysonSphere.layerCount == 0) - { - UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null); - return; - } - DysonShell.s_vmap ??= new Dictionary(16384); - DysonShell.s_outvmap ??= new Dictionary(16384); - DysonShell.s_ivmap ??= new Dictionary(16384); - DysonSphereLayer layer = null; - var nodePos = new List(); - var isEuler = new List(); - DysonShell shell = null; - for (var i = 1; i < dysonSphere.layersIdBased.Length; i++) - { - layer = dysonSphere.layersIdBased[i]; - if (layer == null || layer.id != i) continue; - for (var j = 1; j < layer.shellCursor; j++) - { - shell = layer.shellPool[j]; - if (shell == null) continue; - if (shell.id != j) - { - shell = null; - continue; - } - nodePos.AddRange(shell.nodes.Select(node => node.pos)); - isEuler.AddRange(shell.frames.Select(frame => frame.euler)); - break; - } - if (nodePos.Count > 0) break; - } - if (nodePos.Count == 0) - { - UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null); - return; - } - var currentShellCount = layer.shellCount; - var keepCount = ShellsCountForFunctions.Value; - if (currentShellCount >= keepCount) return; - CheatEnabler.Logger.LogDebug($"NodePositions: {nodePos[0]}, {nodePos[1]}, {nodePos[2]}"); - var nodeCount = nodePos.Count; - DysonNode[] nodes = [.. shell.nodes]; - DysonFrame[] frames = [.. shell.frames]; - if (frames.Length == 0) - { - isEuler = new List(nodeCount); - frames = new DysonFrame[nodeCount]; - for (var i = 0; i < nodeCount; i++) - { - isEuler.Add(false); - frames[i] = layer.QuickAddDysonFrame(0, nodes[i], nodes[(i + 1) % nodeCount], false); - } - } - var cpMax = new long[nodeCount]; - for (var i = 0; i < nodeCount; i++) - { - cpMax[i] = (shell.vertsqOffset[i + 1] - shell.vertsqOffset[i]) * shell.cpPerVertex; - } - long[] totalCpMax = [.. nodes.Select(node => node.totalCpMax)]; - var dirtyFrames = new HashSet(); - for (var i = currentShellCount; i < keepCount; i++) - { - dirtyFrames.Clear(); - for (var j = 0; j < nodeCount; j++) - { - totalCpMax[j] += cpMax[j]; - if (totalCpMax[j] > int.MaxValue) - { - totalCpMax[j] = cpMax[j]; - dirtyFrames.Add(j > 0 ? j - 1 : nodeCount - 1); - dirtyFrames.Add(j); - nodes[j] = layer.QuickAddDysonNode(0, nodePos[j]); - } - } - foreach (var frameId in dirtyFrames) - { - frames[frameId] = layer.QuickAddDysonFrame(0, nodes[frameId], nodes[(frameId + 1) % nodeCount], isEuler[frameId]); - } - 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(); - dysonSphere.inEditorRenderMaskS = 0; - dysonSphere.inEditorRenderMaskL = 0; - dysonSphere.inGameRenderMaskS = 0; - dysonSphere.inGameRenderMaskL = 0; - } - - public static void KeepMaxProductionShells() - { - 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 || dysonSphere.layerCount == 0) - { - UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null); - return; - } - int retainCount = ShellsCountForFunctions.Value; - for (var i = 1; i < dysonSphere.layersIdBased.Length; i++) - { - var layer = dysonSphere.layersIdBased[i]; - if (layer == null || layer.id != i) continue; - var shells = layer.shellPool.Where(shell => shell != null).OrderByDescending(shell => shell.vertexCount).ToArray(); - if (shells.Length < 1) continue; - for (var j = retainCount; j < shells.Length; j++) - { - var shell = shells[j]; - var id = shell.id; - layer.shellPool[id] = null; - for (var k = 0; k < shell.nodes.Count; k++) - { - shell.nodes[k].shells.Remove(shell); - } - shell.Free(); - shells[j] = null; - } - var poolCapacity = AlignUpToPowerOfTwo(retainCount + 1); - if (poolCapacity < 64) poolCapacity = 64; - layer.shellPool = new DysonShell[poolCapacity]; - layer.shellRecycle = new int[poolCapacity]; - layer.shellRecycleCursor = 0; - layer.shellCapacity = poolCapacity; - layer.shellCursor = retainCount + 1; - HashSet retainNodes = []; - HashSet<(int, int)> retainFrames = []; - for (var j = 0; j < retainCount; j++) - { - var shell = shells[j]; - retainNodes.UnionWith(shell.nodes.Select(node => node.id)); - int shellId = j + 1; - layer.shellPool[shellId] = shell; - shell.id = shellId; - for (var k = 0; k < shell.nodes.Count; k++) - { - var idA = shell.nodes[k].id; - var idB = shell.nodes[(k + 1) % shell.nodes.Count].id; - retainFrames.Add((idA, idB)); - retainFrames.Add((idB, idA)); - } - } - var nodes = layer.nodePool.Where(node => node != null && retainNodes.Contains(node.id)).ToArray(); - var frames = layer.framePool.Where(frame => frame != null && retainFrames.Contains((frame.nodeA.id, frame.nodeB.id))).ToArray(); - poolCapacity = AlignUpToPowerOfTwo(frames.Length + 1); - if (poolCapacity < 64) poolCapacity = 64; - layer.framePool = new DysonFrame[poolCapacity]; - layer.frameRecycle = new int[poolCapacity]; - layer.frameRecycleCursor = 0; - layer.frameCapacity = poolCapacity; - layer.frameCursor = frames.Length + 1; - for (var j = 0; j < frames.Length; j++) - { - int id = j + 1; - layer.framePool[id] = frames[j]; - frames[j].id = id; - } - foreach (var node in nodes) - { - if (node != null && node.id > 0) - { - dysonSphere.RemoveDysonNodeRData(node); - } - } - poolCapacity = AlignUpToPowerOfTwo(nodes.Length + 1); - if (poolCapacity < 64) poolCapacity = 64; - layer.nodePool = new DysonNode[poolCapacity]; - layer.nodeRecycle = new int[poolCapacity]; - layer.nodeRecycleCursor = 0; - layer.nodeCapacity = poolCapacity; - layer.nodeCursor = nodes.Length + 1; - for (var j = 0; j < nodes.Length; j++) - { - int id = j + 1; - layer.nodePool[id] = nodes[j]; - nodes[j].id = id; - } - for (var j = 1; j < layer.shellCursor; j++) - { - var shell = layer.shellPool[j]; - if (shell == null || shell.id != j) continue; - shell.nodeIndexMap.Clear(); - for (var k = 0; k < shell.nodes.Count; k++) - { - shell.nodeIndexMap[shell.nodes[k].id] = k; - } - } - for (var j = 1; j < layer.nodeCursor; j++) - { - var node = layer.nodePool[j]; - if (node == null || node.id != j) continue; - dysonSphere.AddDysonNodeRData(node, true); - node.RecalcSpReq(); - node.RecalcCpReq(); - } - } - dysonSphere.CheckAutoNodes(); - if (dysonSphere.autoNodeCount <= 0) - { - dysonSphere.PickAutoNode(); - } - 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(16384); - DysonShell.s_outvmap ??= new Dictionary(16384); - DysonShell.s_ivmap ??= new Dictionary(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(); - 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; - } - } - - private static bool CreateIllegalDysonShellWithMaxOutputForLayer(DysonSphereLayer layer) - { - DysonShell.s_vmap ??= new Dictionary(16384); - DysonShell.s_outvmap ??= new Dictionary(16384); - DysonShell.s_ivmap ??= new Dictionary(16384); - var shellsChanged = false; - var mutex = new object(); - var supposedShells = new List(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)) * layer.orbitRadius; - } - 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)); - CheatEnabler.Logger.LogDebug($"Finished Area Sort"); - var maxVertCount = -1; - var maxJ = -1; - var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount - 1 }; - - var gridScale = (int)(Math.Pow(layer.orbitRadius / 4000.0, 0.75) + 0.5); - gridScale = (gridScale < 1) ? 1 : gridScale; - var cpPerVertex = gridScale * gridScale * 2; - var barrier = 0x7FFFFFFF / cpPerVertex; - if (barrier > 32767) barrier = 32767; - var truncValue = barrier / 1000 * 1000; - CheatEnabler.Logger.LogDebug($"cpPerVertex: {cpPerVertex}, Barrier: {barrier}, TruncValue: {truncValue}"); - - Parallel.For(0, supposedShells.Count, options, (j, loopState) => - { - var sshell = supposedShells[j]; - var vertCount = CalculateTriangleVertCount([sshell.posA, sshell.posB, sshell.posC]); - if (vertCount <= barrier) - { - lock (mutex) - { - if (loopState.ShouldExitCurrentIteration) return; - if (vertCount > maxVertCount) - { - maxVertCount = vertCount; - maxJ = j; - if (maxVertCount >= truncValue) - { - CheatEnabler.Logger.LogDebug($"!!STOP!! Triangle {j}[{sshell.posA:F2} {sshell.posB:F2} {sshell.posC:F2}] has {vertCount} vertices"); - loopState.Stop(); - return; - } - CheatEnabler.Logger.LogDebug($"Triangle {j}[{sshell.posA:F2} {sshell.posB:F2} {sshell.posC:F2}] has {vertCount} vertices"); - } - } - } - }); - if (maxJ >= 0) - { - 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; - var sshell = supposedShells[maxJ]; - DysonNode[] newNodes = [layer.QuickAddDysonNode(0, sshell.posA), layer.QuickAddDysonNode(0, sshell.posB), layer.QuickAddDysonNode(0, sshell.posC)]; - 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; - } - return shellsChanged; - } - - public static void CreateIllegalDysonShellWithMaxOutput() - { - 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; - } - var layer = dysonSphere.layersIdBased[1]; - if (layer != null) - { - dysonSphere.RemoveLayer(1); - } - var maxOrbitRadius = Patches.DysonSpherePatch.UnlockMaxOrbitRadiusEnabled.Value ? Patches.DysonSpherePatch.UnlockMaxOrbitRadiusValue.Value : dysonSphere.maxOrbitRadius; - layer = dysonSphere.AddLayerOnId(1, maxOrbitRadius, Quaternion.Euler(0f, 0f, 0f), Mathf.Sqrt(dysonSphere.gravity / maxOrbitRadius) / maxOrbitRadius * 57.2957802f); - if (layer == null) return; - - var shellsChanged = CreateIllegalDysonShellWithMaxOutputForLayer(layer); - - 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; - } - - public static void CreateIllegalDysonShellWithMaxOutput2() - { - 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; - } - - var shellsChanged = false; - for (int i = dysonSphere.layersSorted.Length - 1; i >= 0; i--) - { - var layer = dysonSphere.layersSorted[i]; - if (layer == null) continue; - shellsChanged = CreateIllegalDysonShellWithMaxOutputForLayer(layer) || shellsChanged; - } - - 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; - } - - public static void CreateIllegalDysonShellsSpecially() - { - var lastGridScale = 0; - var radiusList = new List(); - 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(16384); - DysonShell.s_outvmap ??= new Dictionary(16384); - DysonShell.s_ivmap ??= new Dictionary(16384); - var shellsChanged = false; - var mutex = new object(); - - for (var idx = 1; idx <= 2; idx++) - { - Dictionary<(int, int), int> availableFrames = []; - HashSet 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(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--; - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - return value + 1; - } - - private class SupposedShell - { - public Vector3 posA; - public Vector3 posB; - public Vector3 posC; - - public float area; - public int vertCount; - } + public static void CompleteShellsInstantly() => ShellCompletionFunctions.CompleteShellsInstantly(); + public static void RemoveAllFrames() => FrameRemovalFunctions.RemoveAllFrames(); + public static void DuplicateShellsWithHighestProduction() => IllegalShellFunctions.DuplicateShellsWithHighestProduction(); + public static void KeepMaxProductionShells() => IllegalShellFunctions.KeepMaxProductionShells(); + public static void CreateIllegalDysonShellQuickly(int triangleCount) => IllegalShellFunctions.CreateIllegalDysonShellQuickly(triangleCount); + public static void CreateIllegalDysonShellWithMaxOutput() => IllegalShellFunctions.CreateIllegalDysonShellWithMaxOutput(); + public static void CreateIllegalDysonShellWithMaxOutput2() => IllegalShellFunctions.CreateIllegalDysonShellWithMaxOutput2(); + public static void CreateIllegalDysonShellsSpecially() => IllegalShellFunctions.CreateIllegalDysonShellsSpecially(); }