From 3c384f3a10b95678724285ded1585367db0e8e47 Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Sat, 8 Jan 2022 00:15:37 +0100 Subject: [PATCH 1/9] refactoring power system syncing. guess its really inefficient how i do it atm but its a start. wireless power towers not working for now. --- .../PowerSystem/PowerSystemUpdateRequest.cs | 12 + .../PowerSystem/PowerSystemUpdateResponse.cs | 43 ++ .../PowerTowerUserLoadRequestProcessor.cs | 48 --- .../PowerTowerUserLoadResponseProcessor.cs | 63 --- .../PowerSystemUpdateRequestProcessor.cs | 74 ++++ .../PowerSystemUpdateResponseProcessor.cs | 75 ++++ .../Patches/Dynamic/PowerSystem_Patch.cs | 52 ++- .../Transpilers/PowerSystem_Transpiler.cs | 118 ------ NebulaWorld/Factory/PowerTowerManager.cs | 373 ------------------ NebulaWorld/MultiplayerSession.cs | 5 - 10 files changed, 235 insertions(+), 628 deletions(-) create mode 100644 NebulaModel/Packets/PowerSystem/PowerSystemUpdateRequest.cs create mode 100644 NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs delete mode 100644 NebulaNetwork/PacketProcessors/Factory/PowerTower/PowerTowerUserLoadRequestProcessor.cs delete mode 100644 NebulaNetwork/PacketProcessors/Factory/PowerTower/PowerTowerUserLoadResponseProcessor.cs create mode 100644 NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs create mode 100644 NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs delete mode 100644 NebulaWorld/Factory/PowerTowerManager.cs diff --git a/NebulaModel/Packets/PowerSystem/PowerSystemUpdateRequest.cs b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateRequest.cs new file mode 100644 index 000000000..f44f5e3a6 --- /dev/null +++ b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateRequest.cs @@ -0,0 +1,12 @@ +namespace NebulaModel.Packets.PowerSystem +{ + public class PowerSystemUpdateRequest + { + public int[] PlanetIDs { get; set; } + public PowerSystemUpdateRequest() { } + public PowerSystemUpdateRequest(int[] planetIDs) + { + PlanetIDs = planetIDs; + } + } +} diff --git a/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs new file mode 100644 index 000000000..3eb66c761 --- /dev/null +++ b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs @@ -0,0 +1,43 @@ +namespace NebulaModel.Packets.PowerSystem +{ + public class PowerSystemUpdateResponse + { + // simulate 2d long array with 1d string array separated by ; + public string[] EnergyCapacity { get; set; } + public string[] EnergyRequired { get; set; } + public string[] EnergyServed { get; set; } + public string[] EnergyAccumulated { get; set; } + public string[] EnergyExchanged { get; set; } + public string[] ConsumerRatio { get; set; } + public long[] PowerGenRegister { get; set; } + public long[] PowerConRegister { get; set; } + public long[] PowerDisRegister { get; set; } + public long[] PowerChaRegister { get; set; } + public long[] EnergyConsumption { get; set; } + public PowerSystemUpdateResponse() { } + public PowerSystemUpdateResponse(string[] energyCapacity, + string[] energyRequired, + string[] energyServed, + string[] energyAccumulated, + string[] energyExchanged, + string[] consumerRatio, + long[] powerGenRegister, + long[] powerConRegister, + long[] powerDisRegister, + long[] powerChaRegister, + long[] energyConsumption) + { + EnergyCapacity = energyCapacity; + EnergyRequired = energyRequired; + EnergyServed = energyServed; + EnergyAccumulated = energyAccumulated; + EnergyExchanged = energyExchanged; + ConsumerRatio = consumerRatio; + PowerGenRegister = powerGenRegister; + PowerConRegister = powerConRegister; + PowerDisRegister = powerDisRegister; + PowerChaRegister = powerChaRegister; + EnergyConsumption = energyConsumption; + } + } +} diff --git a/NebulaNetwork/PacketProcessors/Factory/PowerTower/PowerTowerUserLoadRequestProcessor.cs b/NebulaNetwork/PacketProcessors/Factory/PowerTower/PowerTowerUserLoadRequestProcessor.cs deleted file mode 100644 index b8844754a..000000000 --- a/NebulaNetwork/PacketProcessors/Factory/PowerTower/PowerTowerUserLoadRequestProcessor.cs +++ /dev/null @@ -1,48 +0,0 @@ -using NebulaAPI; -using NebulaModel.Networking; -using NebulaModel.Packets; -using NebulaModel.Packets.Factory.PowerTower; -using NebulaWorld; - -namespace NebulaNetwork.PacketProcessors.Factory.PowerTower -{ - [RegisterPacketProcessor] - public class PowerTowerUserLoadingRequestProcessor : PacketProcessor - { - public override void ProcessPacket(PowerTowerUserLoadingRequest packet, NebulaConnection conn) - { - if (IsClient) - { - return; - } - - PlanetFactory factory = GameMain.galaxy.PlanetById(packet.PlanetId)?.factory; - - if (factory?.powerSystem != null) - { - PowerNetwork pNet = factory.powerSystem.netPool[packet.NetId]; - - if (packet.Charging) - { - Multiplayer.Session.PowerTowers.AddExtraDemand(packet.PlanetId, packet.NetId, packet.NodeId, packet.PowerAmount); - } - else - { - Multiplayer.Session.PowerTowers.RemExtraDemand(packet.PlanetId, packet.NetId, packet.NodeId); - } - - Multiplayer.Session.Network.SendPacketToStar(new PowerTowerUserLoadingResponse(packet.PlanetId, - packet.NetId, - packet.NodeId, - packet.PowerAmount, - pNet.energyCapacity, - pNet.energyRequired, - pNet.energyServed, - pNet.energyAccumulated, - pNet.energyExchanged, - packet.Charging), - GameMain.galaxy.PlanetById(packet.PlanetId).star.id); - } - } - } -} \ No newline at end of file diff --git a/NebulaNetwork/PacketProcessors/Factory/PowerTower/PowerTowerUserLoadResponseProcessor.cs b/NebulaNetwork/PacketProcessors/Factory/PowerTower/PowerTowerUserLoadResponseProcessor.cs deleted file mode 100644 index b80e17b1c..000000000 --- a/NebulaNetwork/PacketProcessors/Factory/PowerTower/PowerTowerUserLoadResponseProcessor.cs +++ /dev/null @@ -1,63 +0,0 @@ -using NebulaAPI; -using NebulaModel.Networking; -using NebulaModel.Packets; -using NebulaModel.Packets.Factory.PowerTower; -using NebulaWorld; - -namespace NebulaNetwork.PacketProcessors.Factory.PowerTower -{ - [RegisterPacketProcessor] - internal class PowerTowerUserLoadResponseProcessor : PacketProcessor - { - public override void ProcessPacket(PowerTowerUserLoadingResponse packet, NebulaConnection conn) - { - PlanetFactory factory = GameMain.galaxy.PlanetById(packet.PlanetId)?.factory; - if (factory != null && factory.powerSystem != null) - { - PowerNetwork pNet = factory.powerSystem.netPool[packet.NetId]; - - if (packet.Charging) - { - Multiplayer.Session.PowerTowers.AddExtraDemand(packet.PlanetId, packet.NetId, packet.NodeId, packet.PowerAmount); - if (IsClient) - { - if (Multiplayer.Session.PowerTowers.DidRequest(packet.PlanetId, packet.NetId, packet.NodeId)) - { - int baseDemand = factory.powerSystem.nodePool[packet.NodeId].workEnergyPerTick - factory.powerSystem.nodePool[packet.NodeId].idleEnergyPerTick; - float mult = factory.powerSystem.networkServes[packet.NetId]; - Multiplayer.Session.PowerTowers.PlayerChargeAmount += (int)(mult * baseDemand); - } - } - } - else - { - Multiplayer.Session.PowerTowers.RemExtraDemand(packet.PlanetId, packet.NetId, packet.NodeId); - } - - if (IsHost) - { - Multiplayer.Session.Network.SendPacketToStar(new PowerTowerUserLoadingResponse(packet.PlanetId, - packet.NetId, - packet.NodeId, - packet.PowerAmount, - pNet.energyCapacity, - pNet.energyRequired, - pNet.energyServed, - pNet.energyAccumulated, - pNet.energyExchanged, - packet.Charging), - GameMain.galaxy.PlanetById(packet.PlanetId).star.id); - } - else - { - pNet.energyCapacity = packet.EnergyCapacity; - pNet.energyRequired = packet.EnergyRequired; - pNet.energyAccumulated = packet.EnergyAccumulated; - pNet.energyExchanged = packet.EnergyExchanged; - pNet.energyServed = packet.EnergyServed; - } - - } - } - } -} diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs new file mode 100644 index 000000000..ab95ddf9c --- /dev/null +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs @@ -0,0 +1,74 @@ +using NebulaAPI; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.PowerSystem; + +namespace NebulaNetwork.PacketProcessors.PowerSystem +{ + [RegisterPacketProcessor] + public class PowerSystemUpdateRequestProcessor: PacketProcessor + { + public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnection conn) + { + if (IsClient) + { + return; + } + + // is there a better way? There must be + string[] energyCapacity = new string[packet.PlanetIDs.Length]; + string[] energyRequired = new string[packet.PlanetIDs.Length]; + string[] energyServed = new string[packet.PlanetIDs.Length]; + string[] energyAccumulated = new string[packet.PlanetIDs.Length]; + string[] energyExchanged = new string[packet.PlanetIDs.Length]; + string[] consumerRatio = new string[packet.PlanetIDs.Length]; + long[] powerGenRegister = new long[packet.PlanetIDs.Length]; + long[] powerConRegister = new long[packet.PlanetIDs.Length]; + long[] powerDisRegister = new long[packet.PlanetIDs.Length]; + long[] powerChaRegister = new long[packet.PlanetIDs.Length]; + long[] energyConsumption = new long[packet.PlanetIDs.Length]; + + for(int i = 0; i < packet.PlanetIDs.Length; i++) + { + PlanetData pData = GameMain.galaxy.PlanetById(packet.PlanetIDs[i]); + global::PowerSystem pSys = pData.factory?.powerSystem; + if (pSys != null) + { + for(int j = 0; j < pSys.netCursor; j++) + { + if(j == 0) + { + energyCapacity[i] = pSys.netPool[j].energyCapacity.ToString(); + energyRequired[i] = pSys.netPool[j].energyRequired.ToString(); + energyServed[i] = pSys.netPool[j].energyServed.ToString(); + energyAccumulated[i] = pSys.netPool[j].energyAccumulated.ToString(); + energyExchanged[i] = pSys.netPool[j].energyExchanged.ToString(); + consumerRatio[i] = pSys.netPool[j].consumerRatio.ToString(); + } + else + { + energyCapacity[i] += ";" + pSys.netPool[j].energyCapacity.ToString(); + energyRequired[i] += ";" + pSys.netPool[j].energyRequired.ToString(); + energyServed[i] += ";" + pSys.netPool[j].energyServed.ToString(); + energyAccumulated[i] += ";" + pSys.netPool[j].energyAccumulated.ToString(); + energyExchanged[i] += ";" + pSys.netPool[j].energyExchanged.ToString(); + consumerRatio[i] += ";" + pSys.netPool[j].consumerRatio.ToString(); + } + } + + FactoryProductionStat stats = GameMain.statistics.production.factoryStatPool[pData.factory.index]; + lock (stats) + { + powerGenRegister[i] = stats.powerGenRegister; + powerConRegister[i] = stats.powerConRegister; + powerDisRegister[i] = stats.powerDisRegister; + powerChaRegister[i] = stats.powerChaRegister; + energyConsumption[i] = stats.energyConsumption; + } + } + } + + conn.SendPacket(new PowerSystemUpdateResponse(energyCapacity, energyRequired, energyServed, energyAccumulated, energyExchanged, consumerRatio, powerGenRegister, powerConRegister, powerDisRegister, powerChaRegister, energyConsumption)); + } + } +} diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs new file mode 100644 index 000000000..f2a0d42d3 --- /dev/null +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs @@ -0,0 +1,75 @@ +using NebulaAPI; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.PowerSystem; + +namespace NebulaNetwork.PacketProcessors.PowerSystem +{ + [RegisterPacketProcessor] + public class PowerSystemUpdateResponseProcessor: PacketProcessor + { + public override void ProcessPacket(PowerSystemUpdateResponse packet, NebulaConnection conn) + { + if (IsHost || GameMain.localStar == null) + { + return; + } + + int pIndex = 0; + for(int i = 0; i < GameMain.localStar.planetCount; i++) + { + if(GameMain.localStar.planets[i]?.factory != null) + { + PlanetData pData = GameMain.localStar.planets[i]; + global::PowerSystem pSys = pData.factory?.powerSystem; + + if(pSys != null && pIndex < packet.EnergyCapacity.Length) + { + string[] energyCapacity = packet.EnergyCapacity[pIndex].Split(';'); + string[] energyRequired = packet.EnergyRequired[pIndex].Split(';'); + string[] energyServed = packet.EnergyServed[pIndex].Split(';'); + string[] energyAccumulated = packet.EnergyAccumulated[pIndex].Split(';'); + string[] energyExchanged = packet.EnergyExchanged[pIndex].Split(';'); + string[] consumerRatio = packet.ConsumerRatio[pIndex].Split(';'); + + if(pSys.netCursor != energyCapacity.Length) + { + return; + } + + for(int j = 0; j < pSys.netCursor; j++) + { + long capacity, required, served, accumulated, exchanged, ratio; + + energyCapacity[j].ToLong(out capacity); + energyRequired[j].ToLong(out required); + energyServed[j].ToLong(out served); + energyAccumulated[j].ToLong(out accumulated); + energyExchanged[j].ToLong(out exchanged); + consumerRatio[j].ToLong(out ratio); + + pSys.netPool[j].energyCapacity = capacity; + pSys.netPool[j].energyRequired = required; + pSys.netPool[j].energyServed = served; + pSys.netPool[j].energyAccumulated = accumulated; + pSys.netPool[j].energyExchanged = exchanged; + pSys.netPool[j].consumerRatio = ratio; + } + } + + FactoryProductionStat stats = GameMain.statistics.production.factoryStatPool[pData.factory.index]; + lock (stats) + { + stats.powerGenRegister = packet.PowerGenRegister[pIndex]; + stats.powerConRegister = packet.PowerConRegister[pIndex]; + stats.powerDisRegister = packet.PowerDisRegister[pIndex]; + stats.powerChaRegister = packet.PowerChaRegister[pIndex]; + stats.energyConsumption = packet.EnergyConsumption[pIndex]; + } + + pIndex++; + } + } + } + } +} diff --git a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs index e3a227e52..7c23c23d8 100644 --- a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs @@ -1,39 +1,49 @@ using HarmonyLib; +using NebulaModel.Packets.PowerSystem; using NebulaWorld; +using System.Collections.Generic; +using UnityEngine; namespace NebulaPatcher.Patches.Dynamic { [HarmonyPatch(typeof(PowerSystem))] internal class PowerSystem_Patch { - [HarmonyPostfix] + private const float REQUEST_INTERVAL = 1; + private static float timePassed; + + [HarmonyPrefix] [HarmonyPatch(nameof(PowerSystem.GameTick))] - public static void PowerSystem_GameTick_Postfix(PowerSystem __instance, long time, bool isActive, bool isMultithreadMode) + public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time, bool isActive, bool isMultithreadMode) { - if (Multiplayer.IsActive) + if (Multiplayer.IsActive && Multiplayer.Session.LocalPlayer.IsClient) { - for (int i = 1; i < __instance.netCursor; i++) + // if player is not in a solar system he has no factories loaded, thus nothing to sync here + if(GameMain.localStar == null) { - PowerNetwork pNet = __instance.netPool[i]; - pNet.energyRequired += Multiplayer.Session.PowerTowers.GetExtraDemand(__instance.planet.id, i); + return false; } - Multiplayer.Session.PowerTowers.GivePlayerPower(); - Multiplayer.Session.PowerTowers.UpdateAllAnimations(__instance.planet.id); - } - } - [HarmonyPrefix] - [HarmonyPatch(nameof(PowerSystem.RemoveNodeComponent))] - public static bool RemoveNodeComponent(PowerSystem __instance, int id) - { - if (Multiplayer.IsActive) - { - // as the destruct is synced accross players this event is too - // and as such we can safely remove power demand for every player - PowerNodeComponent pComp = __instance.nodePool[id]; - Multiplayer.Session.PowerTowers.RemExtraDemand(__instance.planet.id, pComp.networkId, id); - } + timePassed += Time.deltaTime; + + if(timePassed >= REQUEST_INTERVAL) + { + timePassed = 0; + + List pIDs = new List(); + for(int i = 0; i < GameMain.localStar.planetCount; i++) + { + if(GameMain.localStar.planets[i]?.factory != null) + { + pIDs.Add(GameMain.localStar.planets[i].id); + } + } + Multiplayer.Session.Network.SendPacket(new PowerSystemUpdateRequest(pIDs.ToArray())); + } + + return false; + } return true; } } diff --git a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs index 3cbbd6d73..2475e1f78 100644 --- a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs +++ b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs @@ -10,124 +10,6 @@ namespace NebulaPatcher.Patches.Transpilers [HarmonyPatch(typeof(PowerSystem))] internal class PowerSystem_Transpiler { - private delegate void PlayerChargesAtTower(PowerSystem _this, int powerNodeId, int powerNetId); - - [HarmonyTranspiler] - [HarmonyPatch(nameof(PowerSystem.GameTick))] - public static IEnumerable PowerSystem_GameTick_Transpiler(IEnumerable instructions) - { - CodeMatcher codeMatcher = new CodeMatcher(instructions) - .MatchForward(true, - new CodeMatch(OpCodes.Ldarg_0), - new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))), - new CodeMatch(OpCodes.Ldloc_S), - new CodeMatch(OpCodes.Ldelema), - new CodeMatch(OpCodes.Ldarg_0), - new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))), - new CodeMatch(OpCodes.Ldloc_S), - new CodeMatch(OpCodes.Ldelema), - new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.workEnergyPerTick))), - new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.requiredEnergy)))); - - if (codeMatcher.IsInvalid) - { - NebulaModel.Logger.Log.Error("PowerSystem_GameTick_Transpiler 1 failed. Mod version not compatible with game version."); - return instructions; - } - - codeMatcher = codeMatcher - .Advance(1) - .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0)) - .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 59)) - .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 22)) - .Insert(HarmonyLib.Transpilers.EmitDelegate((PowerSystem _this, int powerNodeId, int powerNetId) => - { - if (Multiplayer.IsActive) - { - if (!Multiplayer.Session.LocalPlayer.IsHost) - { - _this.nodePool[powerNodeId].requiredEnergy = _this.nodePool[powerNodeId].idleEnergyPerTick; // this gets added onto the known required energy by Multiplayer.Session.PowerTowers. and PowerSystem_Patch - if (Multiplayer.Session.PowerTowers.AddRequested(_this.planet.id, powerNetId, powerNodeId, true, false)) - { - Multiplayer.Session.Network.SendPacket(new PowerTowerUserLoadingRequest(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick, true)); - } - } - else - { - PowerNetwork pNet = _this.netPool[powerNetId]; - if (Multiplayer.Session.PowerTowers.AddRequested(_this.planet.id, powerNetId, powerNodeId, true, false)) - { - Multiplayer.Session.PowerTowers.AddExtraDemand(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick); - Multiplayer.Session.Network.SendPacketToLocalStar(new PowerTowerUserLoadingResponse(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick, - pNet.energyCapacity, - pNet.energyRequired, - pNet.energyServed, - pNet.energyAccumulated, - pNet.energyExchanged, - true)); - } - } - } - })) - // now search for where its set back to idle after player leaves radius / has charged fully - .MatchForward(true, - new CodeMatch(OpCodes.Ldarg_0), - new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))), - new CodeMatch(OpCodes.Ldloc_S), - new CodeMatch(OpCodes.Ldelema), - new CodeMatch(OpCodes.Ldarg_0), - new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.nodePool))), - new CodeMatch(OpCodes.Ldloc_S), - new CodeMatch(OpCodes.Ldelema), - new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.idleEnergyPerTick))), - new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNodeComponent), nameof(PowerNodeComponent.requiredEnergy)))); - - if (codeMatcher.IsInvalid) - { - NebulaModel.Logger.Log.Error("PowerSystem_GameTick_Transpiler 2 failed. Mod version not compatible with game version."); - return codeMatcher.InstructionEnumeration(); - } - - return codeMatcher - .Repeat(matcher => - { - matcher - .Advance(1) - .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0)) - .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 59)) - .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 22)) - .Insert(HarmonyLib.Transpilers.EmitDelegate((PowerSystem _this, int powerNodeId, int powerNetId) => - { - if (Multiplayer.IsActive) - { - if (!Multiplayer.Session.LocalPlayer.IsHost) - { - if (Multiplayer.Session.PowerTowers.AddRequested(_this.planet.id, powerNetId, powerNodeId, false, false)) - { - Multiplayer.Session.Network.SendPacket(new PowerTowerUserLoadingRequest(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick, false)); - } - } - else - { - PowerNetwork pNet = _this.netPool[powerNetId]; - if (Multiplayer.Session.PowerTowers.AddRequested(_this.planet.id, powerNetId, powerNodeId, false, false)) - { - Multiplayer.Session.PowerTowers.RemExtraDemand(_this.planet.id, powerNetId, powerNodeId); - Multiplayer.Session.Network.SendPacketToLocalStar(new PowerTowerUserLoadingResponse(_this.planet.id, powerNetId, powerNodeId, _this.nodePool[powerNodeId].workEnergyPerTick, - pNet.energyCapacity, - pNet.energyRequired, - pNet.energyServed, - pNet.energyAccumulated, - pNet.energyExchanged, - false)); - } - } - } - })); - }) - .InstructionEnumeration(); - } - [HarmonyTranspiler] [HarmonyPatch(nameof(PowerSystem.RequestDysonSpherePower))] public static IEnumerable PowerSystem_RequestDysonSpherePower_Transpiler(IEnumerable instructions) diff --git a/NebulaWorld/Factory/PowerTowerManager.cs b/NebulaWorld/Factory/PowerTowerManager.cs deleted file mode 100644 index d86ba9816..000000000 --- a/NebulaWorld/Factory/PowerTowerManager.cs +++ /dev/null @@ -1,373 +0,0 @@ -using NebulaModel.Logger; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading; - -namespace NebulaWorld.Factory -{ - public class PowerTowerManager : IDisposable - { - public class EnergyMapping - { - public int NetId = 0; - public List NodeId = new List(); - public List Activated = new List(); - public int ExtraPower = 0; - } - - public class Requested - { - public int NetId = 0; - public int NodeId = 0; - public bool Charging = false; - } - - public ConcurrentDictionary> Energy; - public ConcurrentDictionary> RequestsSent; - - public int ChargerCount = 0; - public int PlayerChargeAmount = 0; - - public PowerTowerManager() - { - Energy = new ConcurrentDictionary>(); - RequestsSent = new ConcurrentDictionary>(); - } - - public void Dispose() - { - Energy.Clear(); - Energy = null; - - RequestsSent.Clear(); - RequestsSent = null; - } - - public void GivePlayerPower() - { - if (Multiplayer.Session.LocalPlayer.IsHost) - { - // host gets it anyways - return; - } - - if (PlayerChargeAmount > 0) - { - GameMain.mainPlayer.mecha.coreEnergy += PlayerChargeAmount; - GameMain.mainPlayer.mecha.MarkEnergyChange(2, PlayerChargeAmount); - if (GameMain.mainPlayer.mecha.coreEnergy > GameMain.mainPlayer.mecha.coreEnergyCap) - { - GameMain.mainPlayer.mecha.coreEnergy = GameMain.mainPlayer.mecha.coreEnergyCap; - } - } - } - - // return true if added or changed state, false if already known - public bool AddRequested(int PlanetId, int NetId, int NodeId, bool Charging, bool eventFromOtherPlayer) - { - if (RequestsSent.TryGetValue(PlanetId, out List requests)) - { - for (int i = 0; i < requests.Count; i++) - { - if (requests[i].NetId == NetId && requests[i].NodeId == NodeId) - { - if (requests[i].Charging != Charging) - { - if (Charging == false) - { - PlanetFactory factory = GameMain.galaxy.PlanetById(PlanetId)?.factory; - - if (factory != null && factory.powerSystem != null) - { - int baseDemand = factory.powerSystem.nodePool[NodeId].workEnergyPerTick - factory.powerSystem.nodePool[NodeId].idleEnergyPerTick; - float mult = factory.powerSystem.networkServes[NetId]; - - PlayerChargeAmount -= (int)(mult * baseDemand); - ChargerCount--; - - if (PlayerChargeAmount < 0) - { - PlayerChargeAmount = 0; - } - if (ChargerCount == 0) - { - PlayerChargeAmount = 0; - } - } - } - if (!eventFromOtherPlayer) - { - requests[i].Charging = Charging; - } - return true; - } - return false; - } - } - - Requested req = new Requested - { - NetId = NetId, - NodeId = NodeId - }; - - requests.Add(req); - - return true; - } - - List list = new List(); - Requested req2 = new Requested - { - NetId = NetId, - NodeId = NodeId - }; - - list.Add(req2); - return RequestsSent.TryAdd(PlanetId, list); - } - - public bool DidRequest(int PlanetId, int NetId, int NodeId) - { - if (RequestsSent.TryGetValue(PlanetId, out List requests)) - { - for (int i = 0; i < requests.Count; i++) - { - if (requests[i].NetId == NetId && requests[i].NodeId == NodeId && requests[i].Charging) - { - ChargerCount++; - return true; - } - } - } - - return false; - } - - public int GetExtraDemand(int PlanetId, int NetId) - { - - if (Energy.TryGetValue(PlanetId, out List mapping)) - { - if (Monitor.TryEnter(mapping, 100)) - { - try - { - for (int i = 0; i < mapping.Count; i++) - { - if (mapping[i].NetId == NetId) - { - return mapping[i].ExtraPower; - } - } - } - finally - { - Monitor.Exit(mapping); - } - } - else - { - Log.Warn($"PowerTower: cant wait longer for threading lock, PowerTowers will be desynced!"); - } - } - - return 0; - } - - public void RemExtraDemand(int PlanetId, int NetId, int NodeId) - { - if (Energy.TryGetValue(PlanetId, out List mapping)) - { - for (int i = 0; i < mapping.Count; i++) - { - if (mapping[i].NetId == NetId) - { - PlanetFactory factory = GameMain.galaxy.PlanetById(PlanetId).factory; - PowerSystem pSystem = factory?.powerSystem; - - if (Monitor.TryEnter(mapping, 100)) - { - try - { - for (int j = 0; j < mapping[i].NodeId.Count; j++) - { - if (mapping[i].NodeId[j] == NodeId) - { - if (factory != null && pSystem != null) - { - mapping[i].ExtraPower -= pSystem.nodePool[NodeId].workEnergyPerTick; - } - else - { - mapping[i].ExtraPower -= mapping[i].ExtraPower / mapping[i].NodeId.Count; - } - - mapping[i].Activated[j]--; - AddRequested(PlanetId, NetId, NodeId, false, true); - - break; - } - } - } - finally - { - Monitor.Exit(mapping); - } - } - else - { - Log.Warn($"PowerTower: cant wait longer for threading lock, PowerTowers will be desynced!"); - } - - if (mapping[i].ExtraPower < 0) - { - mapping[i].ExtraPower = 0; - } - } - } - } - } - - public void AddExtraDemand(int PlanetId, int NetId, int NodeId, int PowerAmount) - { - if (Energy.TryGetValue(PlanetId, out List mapping)) - { - for (int i = 0; i < mapping.Count; i++) - { - if (Monitor.TryEnter(mapping, 100)) - { - try - { - if (mapping[i].NetId == NetId) - { - bool foundNodeId = false; - for (int j = 0; j < mapping[i].NodeId.Count; j++) - { - if (mapping[i].NodeId[j] == NodeId) - { - foundNodeId = true; - mapping[i].Activated[j]++; - mapping[i].ExtraPower += PowerAmount; - break; - } - } - - if (!foundNodeId) - { - mapping[i].NodeId.Add(NodeId); - mapping[i].Activated.Add(1); - mapping[i].ExtraPower += PowerAmount; - } - - return; - } - } - finally - { - Monitor.Exit(mapping); - } - } - else - { - Log.Warn($"PowerTower: cant wait longer for threading lock, PowerTowers will be desynced!"); - } - } - - if (Monitor.TryEnter(mapping, 100)) - { - try - { - EnergyMapping map = new EnergyMapping - { - NetId = NetId - }; - map.NodeId.Add(NodeId); - map.Activated.Add(1); - map.ExtraPower = PowerAmount; - - mapping.Add(map); - } - finally - { - Monitor.Exit(mapping); - } - } - else - { - Log.Warn($"PowerTower: cant wait longer for threading lock, PowerTowers will be desynced!"); - } - } - else - { - List mapping2 = new List(); - - EnergyMapping map = new EnergyMapping - { - NetId = NetId - }; - map.NodeId.Add(NodeId); - map.Activated.Add(1); - map.ExtraPower = PowerAmount; - - mapping2.Add(map); - if (!Energy.TryAdd(PlanetId, mapping2)) - { - // if we failed to add then most likely because another thread was faster, so call this again to run the above part of the method. - AddExtraDemand(PlanetId, NetId, NodeId, PowerAmount); - } - } - } - - public void UpdateAllAnimations(int PlanetId) - { - if (Energy.TryGetValue(PlanetId, out List mapping)) - { - if (Monitor.TryEnter(mapping, 100)) - { - try - { - for (int i = 0; i < mapping.Count; i++) - { - for (int j = 0; j < mapping[i].Activated.Count; j++) - { - UpdateAnimation(PlanetId, mapping[i].NetId, mapping[i].NodeId[j], mapping[i].Activated[j] > 0 ? 1 : 0); - } - } - } - finally - { - Monitor.Exit(mapping); - } - } - else - { - Log.Warn($"PowerTower: cant wait longer for threading lock, PowerTowers will be desynced!"); - } - } - } - - public void UpdateAnimation(int PlanetId, int NetId, int NodeId, int PowerAmount) - { - float idkValue = 0.016666668f; - PlanetFactory factory = GameMain.galaxy.PlanetById(PlanetId)?.factory; - - if (factory != null && factory.entityAnimPool != null && factory.powerSystem != null) - { - PowerNodeComponent pComp = factory.powerSystem.nodePool[NodeId]; - AnimData[] animPool = factory.entityAnimPool; - int entityId = pComp.entityId; - - if (pComp.coverRadius < 15f) - { - animPool[entityId].StepPoweredClamped(factory.powerSystem.networkServes[NetId], idkValue, (PowerAmount > 0) ? 2U : 1U); - } - else - { - animPool[entityId].StepPoweredClamped2(factory.powerSystem.networkServes[NetId], idkValue, (PowerAmount > 0) ? 2U : 1U); - } - } - } - } -} diff --git a/NebulaWorld/MultiplayerSession.cs b/NebulaWorld/MultiplayerSession.cs index aff492949..15887cc1f 100644 --- a/NebulaWorld/MultiplayerSession.cs +++ b/NebulaWorld/MultiplayerSession.cs @@ -20,7 +20,6 @@ public class MultiplayerSession : IDisposable, IMultiplayerSession public SimulatedWorld World { get; private set; } public IFactoryManager Factories { get; private set; } public StorageManager Storage { get; private set; } - public PowerTowerManager PowerTowers { get; private set; } public BeltManager Belts { get; private set; } public BuildToolManager BuildTools { get; private set; } public DroneManager Drones { get; private set; } @@ -59,7 +58,6 @@ public MultiplayerSession(NetworkProvider networkProvider) World = new SimulatedWorld(); Factories = new FactoryManager(); Storage = new StorageManager(); - PowerTowers = new PowerTowerManager(); Belts = new BeltManager(); BuildTools = new BuildToolManager(); Drones = new DroneManager(); @@ -90,9 +88,6 @@ public void Dispose() Storage?.Dispose(); Storage = null; - PowerTowers?.Dispose(); - PowerTowers = null; - Belts?.Dispose(); Belts = null; From 24e3931cf0d70467fd9e9c63afbc3cc784a1c105 Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Sat, 8 Jan 2022 23:26:46 +0100 Subject: [PATCH 2/9] use proper serialization of 2d arrays --- .../Networking/Serialization/NetSerializer.cs | 105 ++++++++++++++---- .../PowerSystem/PowerSystemUpdateResponse.cs | 24 ++-- .../PowerSystemUpdateRequestProcessor.cs | 43 ++++--- .../PowerSystemUpdateResponseProcessor.cs | 46 +++----- 4 files changed, 131 insertions(+), 87 deletions(-) diff --git a/NebulaModel/Networking/Serialization/NetSerializer.cs b/NebulaModel/Networking/Serialization/NetSerializer.cs index 661fda66d..ace6b8e3b 100644 --- a/NebulaModel/Networking/Serialization/NetSerializer.cs +++ b/NebulaModel/Networking/Serialization/NetSerializer.cs @@ -469,6 +469,58 @@ private class StringSerializer : FastCallSpecific public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf), _maxLength); } } + private class Long2ArraySerializer : FastCallSpecific + { + public override void Read(T inf, NetDataReader r) + { + ushort size = r.GetUShort(); + long[][] arr = new long[size][]; + + for(int i = 0; i < size; i++) + { + arr[i] = r.GetLongArray(); + } + + Setter(inf, arr); + } + public override void Write(T inf, NetDataWriter w) + { + ushort len = Getter(inf) == null ? (ushort)0 : (ushort)Getter(inf).Length; + + w.Put(len); + for(int i = 0; i < len; i++) + { + w.PutArray(Getter(inf)[i]); + } + } + } + + private class Double2ArraySerializer : FastCallSpecific + { + public override void Read(T inf, NetDataReader r) + { + ushort size = r.GetUShort(); + double[][] arr = new double[size][]; + + for (int i = 0; i < size; i++) + { + arr[i] = r.GetDoubleArray(); + } + + Setter(inf, arr); + } + public override void Write(T inf, NetDataWriter w) + { + ushort len = Getter(inf) == null ? (ushort)0 : (ushort)Getter(inf).Length; + + w.Put(len); + for (int i = 0; i < len; i++) + { + w.PutArray(Getter(inf)[i]); + } + } + } + private class EnumByteSerializer : FastCall { protected readonly PropertyInfo Property; @@ -637,7 +689,8 @@ private ClassInfo RegisterInternal() Type propertyType = property.PropertyType; Type elementType = propertyType.IsArray ? propertyType.GetElementType() : propertyType; - CallType callType = propertyType.IsArray ? CallType.Array : CallType.Basic; + // todo: find a better way to handle 2d arrays in the Init() method + CallType callType = (propertyType.IsArray && elementType != typeof(long[]) && elementType != typeof(double[])) ? CallType.Array : CallType.Basic; if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>)) { @@ -657,17 +710,17 @@ private ClassInfo RegisterInternal() continue; } - FastCall serialzer = null; + FastCall serializer = null; if (propertyType.IsEnum) { Type underlyingType = Enum.GetUnderlyingType(propertyType); if (underlyingType == typeof(byte)) { - serialzer = new EnumByteSerializer(property, propertyType); + serializer = new EnumByteSerializer(property, propertyType); } else if (underlyingType == typeof(int)) { - serialzer = new EnumIntSerializer(property, propertyType); + serializer = new EnumIntSerializer(property, propertyType); } else { @@ -676,73 +729,81 @@ private ClassInfo RegisterInternal() } else if (elementType == typeof(string)) { - serialzer = new StringSerializer(_maxStringLength); + serializer = new StringSerializer(_maxStringLength); } else if (elementType == typeof(bool)) { - serialzer = new BoolSerializer(); + serializer = new BoolSerializer(); } else if (elementType == typeof(byte)) { - serialzer = new ByteSerializer(); + serializer = new ByteSerializer(); } else if (elementType == typeof(sbyte)) { - serialzer = new SByteSerializer(); + serializer = new SByteSerializer(); } else if (elementType == typeof(short)) { - serialzer = new ShortSerializer(); + serializer = new ShortSerializer(); } else if (elementType == typeof(ushort)) { - serialzer = new UShortSerializer(); + serializer = new UShortSerializer(); } else if (elementType == typeof(int)) { - serialzer = new IntSerializer(); + serializer = new IntSerializer(); } else if (elementType == typeof(uint)) { - serialzer = new UIntSerializer(); + serializer = new UIntSerializer(); } else if (elementType == typeof(long)) { - serialzer = new LongSerializer(); + serializer = new LongSerializer(); } else if (elementType == typeof(ulong)) { - serialzer = new ULongSerializer(); + serializer = new ULongSerializer(); } else if (elementType == typeof(float)) { - serialzer = new FloatSerializer(); + serializer = new FloatSerializer(); } else if (elementType == typeof(double)) { - serialzer = new DoubleSerializer(); + serializer = new DoubleSerializer(); } else if (elementType == typeof(char)) { - serialzer = new CharSerializer(); + serializer = new CharSerializer(); } else if (elementType == typeof(IPEndPoint)) { - serialzer = new IPEndPointSerializer(); + serializer = new IPEndPointSerializer(); + } + else if(elementType == typeof(long[])) // handles long[][] + { + serializer = new Long2ArraySerializer(); + } + else if(elementType == typeof(double[])) // handles double[][] + { + serializer = new Double2ArraySerializer(); } else { _registeredTypes.TryGetValue(elementType, out CustomType customType); if (customType != null) { - serialzer = customType.Get(); + serializer = customType.Get(); } } - if (serialzer != null) + if (serializer != null) { - serialzer.Init(getMethod, setMethod, callType); - serializers.Add(serialzer); + serializer.Init(getMethod, setMethod, callType); + serializers.Add(serializer); } else { diff --git a/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs index 3eb66c761..f657d6766 100644 --- a/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs +++ b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs @@ -3,24 +3,24 @@ public class PowerSystemUpdateResponse { // simulate 2d long array with 1d string array separated by ; - public string[] EnergyCapacity { get; set; } - public string[] EnergyRequired { get; set; } - public string[] EnergyServed { get; set; } - public string[] EnergyAccumulated { get; set; } - public string[] EnergyExchanged { get; set; } - public string[] ConsumerRatio { get; set; } + public long[][] EnergyCapacity { get; set; } + public long[][] EnergyRequired { get; set; } + public long[][] EnergyServed { get; set; } + public long[][] EnergyAccumulated { get; set; } + public long[][] EnergyExchanged { get; set; } + public double[][] ConsumerRatio { get; set; } public long[] PowerGenRegister { get; set; } public long[] PowerConRegister { get; set; } public long[] PowerDisRegister { get; set; } public long[] PowerChaRegister { get; set; } public long[] EnergyConsumption { get; set; } public PowerSystemUpdateResponse() { } - public PowerSystemUpdateResponse(string[] energyCapacity, - string[] energyRequired, - string[] energyServed, - string[] energyAccumulated, - string[] energyExchanged, - string[] consumerRatio, + public PowerSystemUpdateResponse(long[][] energyCapacity, + long[][] energyRequired, + long[][] energyServed, + long[][] energyAccumulated, + long[][] energyExchanged, + double[][] consumerRatio, long[] powerGenRegister, long[] powerConRegister, long[] powerDisRegister, diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs index ab95ddf9c..3f2001ef7 100644 --- a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs @@ -16,12 +16,12 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec } // is there a better way? There must be - string[] energyCapacity = new string[packet.PlanetIDs.Length]; - string[] energyRequired = new string[packet.PlanetIDs.Length]; - string[] energyServed = new string[packet.PlanetIDs.Length]; - string[] energyAccumulated = new string[packet.PlanetIDs.Length]; - string[] energyExchanged = new string[packet.PlanetIDs.Length]; - string[] consumerRatio = new string[packet.PlanetIDs.Length]; + long[][] energyCapacity = new long[packet.PlanetIDs.Length][]; + long[][] energyRequired = new long[packet.PlanetIDs.Length][]; + long[][] energyServed = new long[packet.PlanetIDs.Length][]; + long[][] energyAccumulated = new long[packet.PlanetIDs.Length][]; + long[][] energyExchanged = new long[packet.PlanetIDs.Length][]; + double[][] consumerRatio = new double[packet.PlanetIDs.Length][]; long[] powerGenRegister = new long[packet.PlanetIDs.Length]; long[] powerConRegister = new long[packet.PlanetIDs.Length]; long[] powerDisRegister = new long[packet.PlanetIDs.Length]; @@ -34,26 +34,21 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec global::PowerSystem pSys = pData.factory?.powerSystem; if (pSys != null) { + energyCapacity[i] = new long[pSys.netCursor]; + energyRequired[i] = new long[pSys.netCursor]; + energyServed[i] = new long[pSys.netCursor]; + energyAccumulated[i] = new long[pSys.netCursor]; + energyExchanged[i] = new long[pSys.netCursor]; + consumerRatio[i] = new double[pSys.netCursor]; + for(int j = 0; j < pSys.netCursor; j++) { - if(j == 0) - { - energyCapacity[i] = pSys.netPool[j].energyCapacity.ToString(); - energyRequired[i] = pSys.netPool[j].energyRequired.ToString(); - energyServed[i] = pSys.netPool[j].energyServed.ToString(); - energyAccumulated[i] = pSys.netPool[j].energyAccumulated.ToString(); - energyExchanged[i] = pSys.netPool[j].energyExchanged.ToString(); - consumerRatio[i] = pSys.netPool[j].consumerRatio.ToString(); - } - else - { - energyCapacity[i] += ";" + pSys.netPool[j].energyCapacity.ToString(); - energyRequired[i] += ";" + pSys.netPool[j].energyRequired.ToString(); - energyServed[i] += ";" + pSys.netPool[j].energyServed.ToString(); - energyAccumulated[i] += ";" + pSys.netPool[j].energyAccumulated.ToString(); - energyExchanged[i] += ";" + pSys.netPool[j].energyExchanged.ToString(); - consumerRatio[i] += ";" + pSys.netPool[j].consumerRatio.ToString(); - } + energyCapacity[i][j] = pSys.netPool[j].energyCapacity; + energyRequired[i][j] = pSys.netPool[j].energyRequired; + energyServed[i][j] = pSys.netPool[j].energyServed; + energyAccumulated[i][j] = pSys.netPool[j].energyAccumulated; + energyExchanged[i][j] = pSys.netPool[j].energyExchanged; + consumerRatio[i][j] = pSys.netPool[j].consumerRatio; } FactoryProductionStat stats = GameMain.statistics.production.factoryStatPool[pData.factory.index]; diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs index f2a0d42d3..8b76bd080 100644 --- a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs @@ -25,46 +25,33 @@ public override void ProcessPacket(PowerSystemUpdateResponse packet, NebulaConne if(pSys != null && pIndex < packet.EnergyCapacity.Length) { - string[] energyCapacity = packet.EnergyCapacity[pIndex].Split(';'); - string[] energyRequired = packet.EnergyRequired[pIndex].Split(';'); - string[] energyServed = packet.EnergyServed[pIndex].Split(';'); - string[] energyAccumulated = packet.EnergyAccumulated[pIndex].Split(';'); - string[] energyExchanged = packet.EnergyExchanged[pIndex].Split(';'); - string[] consumerRatio = packet.ConsumerRatio[pIndex].Split(';'); - - if(pSys.netCursor != energyCapacity.Length) + if(pSys.netCursor != packet.EnergyCapacity[pIndex].Length) { return; } for(int j = 0; j < pSys.netCursor; j++) { - long capacity, required, served, accumulated, exchanged, ratio; - - energyCapacity[j].ToLong(out capacity); - energyRequired[j].ToLong(out required); - energyServed[j].ToLong(out served); - energyAccumulated[j].ToLong(out accumulated); - energyExchanged[j].ToLong(out exchanged); - consumerRatio[j].ToLong(out ratio); - - pSys.netPool[j].energyCapacity = capacity; - pSys.netPool[j].energyRequired = required; - pSys.netPool[j].energyServed = served; - pSys.netPool[j].energyAccumulated = accumulated; - pSys.netPool[j].energyExchanged = exchanged; - pSys.netPool[j].consumerRatio = ratio; + pSys.netPool[j].energyCapacity = packet.EnergyCapacity[pIndex][j]; + pSys.netPool[j].energyRequired = packet.EnergyRequired[pIndex][j]; + pSys.netPool[j].energyServed = packet.EnergyServed[pIndex][j]; + pSys.netPool[j].energyAccumulated = packet.EnergyAccumulated[pIndex][j]; + pSys.netPool[j].energyExchanged = packet.EnergyExchanged[pIndex][j]; + pSys.netPool[j].consumerRatio = packet.ConsumerRatio[pIndex][j]; } } FactoryProductionStat stats = GameMain.statistics.production.factoryStatPool[pData.factory.index]; - lock (stats) + if(pIndex < packet.PowerGenRegister.Length) { - stats.powerGenRegister = packet.PowerGenRegister[pIndex]; - stats.powerConRegister = packet.PowerConRegister[pIndex]; - stats.powerDisRegister = packet.PowerDisRegister[pIndex]; - stats.powerChaRegister = packet.PowerChaRegister[pIndex]; - stats.energyConsumption = packet.EnergyConsumption[pIndex]; + lock (stats) + { + stats.powerGenRegister = packet.PowerGenRegister[pIndex]; + stats.powerConRegister = packet.PowerConRegister[pIndex]; + stats.powerDisRegister = packet.PowerDisRegister[pIndex]; + stats.powerChaRegister = packet.PowerChaRegister[pIndex]; + stats.energyConsumption = packet.EnergyConsumption[pIndex]; + } } pIndex++; @@ -73,3 +60,4 @@ public override void ProcessPacket(PowerSystemUpdateResponse packet, NebulaConne } } } + From 29300be71fae8bfb0246ec93482003a47d0ea295 Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Sun, 9 Jan 2022 01:51:40 +0100 Subject: [PATCH 3/9] better lobby check --- NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs index 06535c2b8..829bd90a7 100644 --- a/NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs @@ -58,7 +58,7 @@ public static bool _OnUpdate_Prefix(UIPlanetDetail __instance) [HarmonyPatch(nameof(UIPlanetDetail.RefreshDynamicProperties))] public static bool OnPlanetDataSet_Prefix(UIPlanetDetail __instance) { - if(UIRoot.instance.galaxySelect.starmap.clickText != "") + if(Multiplayer.Session != null && Multiplayer.Session.IsInLobby) { BackupUniverseObserveLevel = GameMain.history.universeObserveLevel; GameMain.history.universeObserveLevel = 3; @@ -71,7 +71,7 @@ public static bool OnPlanetDataSet_Prefix(UIPlanetDetail __instance) [HarmonyPatch(nameof(UIPlanetDetail.RefreshDynamicProperties))] public static void OnPlanetDataSet_Postfix(UIPlanetDetail __instance) { - if(BackupUniverseObserveLevel != -1) + if(BackupUniverseObserveLevel != -1 && Multiplayer.Session != null && Multiplayer.Session.IsInLobby) { GameMain.history.universeObserveLevel = BackupUniverseObserveLevel; BackupUniverseObserveLevel = -1; From 9d8052a72ecfb879707eebf6568d71a900cb7d2f Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Sat, 15 Jan 2022 06:31:45 +0100 Subject: [PATCH 4/9] started to refactor/implement power system syncing. wip --- .../Networking/Serialization/NetSerializer.cs | 32 ++++- .../PowerSystem/PowerSystemUpdateResponse.cs | 42 +++--- .../PowerSystemUpdateRequestProcessor.cs | 77 ++++++++--- .../PowerSystemUpdateResponseProcessor.cs | 74 +++++++++-- .../Patches/Dynamic/PowerSystem_Patch.cs | 124 ++++++++++++++++++ .../Patches/Dynamic/UIPlanetDetail_Patch.cs | 4 +- .../Transpilers/PowerSystem_Transpiler.cs | 65 ++++++++- NebulaWorld/Factory/PowerSystemManager.cs | 10 ++ 8 files changed, 377 insertions(+), 51 deletions(-) create mode 100644 NebulaWorld/Factory/PowerSystemManager.cs diff --git a/NebulaModel/Networking/Serialization/NetSerializer.cs b/NebulaModel/Networking/Serialization/NetSerializer.cs index ace6b8e3b..86d6b9cdc 100644 --- a/NebulaModel/Networking/Serialization/NetSerializer.cs +++ b/NebulaModel/Networking/Serialization/NetSerializer.cs @@ -521,6 +521,32 @@ public override void Write(T inf, NetDataWriter w) } } + private class Bool2ArraySerializer : FastCallSpecific + { + public override void Read(T inf, NetDataReader r) + { + ushort size = r.GetUShort(); + bool[][] arr = new bool[size][]; + + for (int i = 0; i < size; i++) + { + arr[i] = r.GetBoolArray(); + } + + Setter(inf, arr); + } + public override void Write(T inf, NetDataWriter w) + { + ushort len = Getter(inf) == null ? (ushort)0 : (ushort)Getter(inf).Length; + + w.Put(len); + for (int i = 0; i < len; i++) + { + w.PutArray(Getter(inf)[i]); + } + } + } + private class EnumByteSerializer : FastCall { protected readonly PropertyInfo Property; @@ -690,7 +716,7 @@ private ClassInfo RegisterInternal() Type elementType = propertyType.IsArray ? propertyType.GetElementType() : propertyType; // todo: find a better way to handle 2d arrays in the Init() method - CallType callType = (propertyType.IsArray && elementType != typeof(long[]) && elementType != typeof(double[])) ? CallType.Array : CallType.Basic; + CallType callType = (propertyType.IsArray && elementType != typeof(long[]) && elementType != typeof(double[]) && elementType != typeof(bool[])) ? CallType.Array : CallType.Basic; if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>)) { @@ -791,6 +817,10 @@ private ClassInfo RegisterInternal() { serializer = new Double2ArraySerializer(); } + else if(elementType == typeof(bool[])) // handles bool[][] + { + serializer = new Bool2ArraySerializer(); + } else { _registeredTypes.TryGetValue(elementType, out CustomType customType); diff --git a/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs index f657d6766..10ba86d3e 100644 --- a/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs +++ b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs @@ -3,36 +3,48 @@ public class PowerSystemUpdateResponse { // simulate 2d long array with 1d string array separated by ; - public long[][] EnergyCapacity { get; set; } - public long[][] EnergyRequired { get; set; } - public long[][] EnergyServed { get; set; } - public long[][] EnergyAccumulated { get; set; } - public long[][] EnergyExchanged { get; set; } + //public long[][] EnergyCapacity { get; set; } + //public long[][] EnergyRequired { get; set; } + //public long[][] EnergyServed { get; set; } + //public long[][] EnergyAccumulated { get; set; } + //public long[][] EnergyExchanged { get; set; } public double[][] ConsumerRatio { get; set; } + public double[][] GeneratorRatio { get; set; } + public bool[][] CopyValues { get; set; } + public long[][] GenerateCurrentTick { get; set; } + public bool[][] TogglePower { get; set; } public long[] PowerGenRegister { get; set; } public long[] PowerConRegister { get; set; } public long[] PowerDisRegister { get; set; } public long[] PowerChaRegister { get; set; } public long[] EnergyConsumption { get; set; } public PowerSystemUpdateResponse() { } - public PowerSystemUpdateResponse(long[][] energyCapacity, - long[][] energyRequired, - long[][] energyServed, - long[][] energyAccumulated, - long[][] energyExchanged, + public PowerSystemUpdateResponse(//long[][] energyCapacity, + //long[][] energyRequired, + //long[][] energyServed, + //long[][] energyAccumulated, + //long[][] energyExchanged, double[][] consumerRatio, + double[][] generatorRatio, + bool[][] copyValues, + long[][] generateCurrentTick, + bool[][] togglePower, long[] powerGenRegister, long[] powerConRegister, long[] powerDisRegister, long[] powerChaRegister, long[] energyConsumption) { - EnergyCapacity = energyCapacity; - EnergyRequired = energyRequired; - EnergyServed = energyServed; - EnergyAccumulated = energyAccumulated; - EnergyExchanged = energyExchanged; + //EnergyCapacity = energyCapacity; + //EnergyRequired = energyRequired; + //EnergyServed = energyServed; + //EnergyAccumulated = energyAccumulated; + //EnergyExchanged = energyExchanged; ConsumerRatio = consumerRatio; + GeneratorRatio = generatorRatio; + CopyValues = copyValues; + GenerateCurrentTick = generateCurrentTick; + TogglePower = togglePower; PowerGenRegister = powerGenRegister; PowerConRegister = powerConRegister; PowerDisRegister = powerDisRegister; diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs index 3f2001ef7..f847ed1e4 100644 --- a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs @@ -1,7 +1,9 @@ using NebulaAPI; +using NebulaModel.Logger; using NebulaModel.Networking; using NebulaModel.Packets; using NebulaModel.Packets.PowerSystem; +using NebulaWorld.Factory; namespace NebulaNetwork.PacketProcessors.PowerSystem { @@ -16,12 +18,16 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec } // is there a better way? There must be - long[][] energyCapacity = new long[packet.PlanetIDs.Length][]; - long[][] energyRequired = new long[packet.PlanetIDs.Length][]; - long[][] energyServed = new long[packet.PlanetIDs.Length][]; - long[][] energyAccumulated = new long[packet.PlanetIDs.Length][]; - long[][] energyExchanged = new long[packet.PlanetIDs.Length][]; + //long[][] energyCapacity = new long[packet.PlanetIDs.Length][]; + //long[][] energyRequired = new long[packet.PlanetIDs.Length][]; + //long[][] energyServed = new long[packet.PlanetIDs.Length][]; + //long[][] energyAccumulated = new long[packet.PlanetIDs.Length][]; + //long[][] energyExchanged = new long[packet.PlanetIDs.Length][]; double[][] consumerRatio = new double[packet.PlanetIDs.Length][]; + double[][] generatorRatio = new double[packet.PlanetIDs.Length][]; + bool[][] copyValues = new bool[packet.PlanetIDs.Length][]; + long[][] generateCurrentTick = new long[packet.PlanetIDs.Length][]; + bool[][] togglePower = new bool[packet.PlanetIDs.Length][]; long[] powerGenRegister = new long[packet.PlanetIDs.Length]; long[] powerConRegister = new long[packet.PlanetIDs.Length]; long[] powerDisRegister = new long[packet.PlanetIDs.Length]; @@ -31,24 +37,57 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec for(int i = 0; i < packet.PlanetIDs.Length; i++) { PlanetData pData = GameMain.galaxy.PlanetById(packet.PlanetIDs[i]); - global::PowerSystem pSys = pData.factory?.powerSystem; + global::PowerSystem pSys = pData?.factory?.powerSystem; if (pSys != null) { - energyCapacity[i] = new long[pSys.netCursor]; - energyRequired[i] = new long[pSys.netCursor]; - energyServed[i] = new long[pSys.netCursor]; - energyAccumulated[i] = new long[pSys.netCursor]; - energyExchanged[i] = new long[pSys.netCursor]; + //energyCapacity[i] = new long[pSys.netCursor]; + //energyRequired[i] = new long[pSys.netCursor]; + //energyServed[i] = new long[pSys.netCursor]; + //energyAccumulated[i] = new long[pSys.netCursor]; + //energyExchanged[i] = new long[pSys.netCursor]; consumerRatio[i] = new double[pSys.netCursor]; + generatorRatio[i] = new double[pSys.netCursor]; + copyValues[i] = new bool[pSys.netCursor]; + generateCurrentTick[i] = new long[pSys.netCursor]; + togglePower[i] = new bool[pSys.netCursor]; - for(int j = 0; j < pSys.netCursor; j++) + // netPool starts at index 1 but our array starts at index 0 :/ + for(int j = 0; j < pSys.netCursor - 1; j++) { - energyCapacity[i][j] = pSys.netPool[j].energyCapacity; - energyRequired[i][j] = pSys.netPool[j].energyRequired; - energyServed[i][j] = pSys.netPool[j].energyServed; - energyAccumulated[i][j] = pSys.netPool[j].energyAccumulated; - energyExchanged[i][j] = pSys.netPool[j].energyExchanged; - consumerRatio[i][j] = pSys.netPool[j].consumerRatio; + //energyCapacity[i][j] = pSys.netPool[j].energyCapacity; + //energyRequired[i][j] = pSys.netPool[j].energyRequired; + //energyServed[i][j] = pSys.netPool[j].energyServed; + //energyAccumulated[i][j] = pSys.netPool[j].energyAccumulated; + //energyExchanged[i][j] = pSys.netPool[j].energyExchanged; + consumerRatio[i][j] = pSys.netPool[j + 1].consumerRatio; + generatorRatio[i][j] = pSys.netPool[j + 1].generaterRatio; + + if(pSys.netPool[j + 1].generators.Count > 0) + { + generateCurrentTick[i][j] = pSys.genPool[pSys.netPool[j + 1].generators[0]].generateCurrentTick; + } + else + { + generateCurrentTick[i][j] = 0; + } + + if (PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pData.id, out var list)) + { + togglePower[i][j] = j < list.Count && list[j] > 0; + } + else + { + togglePower[i][j] = false; + } + + if((float)pSys.netPool[j + 1].consumerRatio == pSys.networkServes[j]) + { + copyValues[i][j] = true; + } + else + { + copyValues[i][j] = false; + } } FactoryProductionStat stats = GameMain.statistics.production.factoryStatPool[pData.factory.index]; @@ -63,7 +102,7 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec } } - conn.SendPacket(new PowerSystemUpdateResponse(energyCapacity, energyRequired, energyServed, energyAccumulated, energyExchanged, consumerRatio, powerGenRegister, powerConRegister, powerDisRegister, powerChaRegister, energyConsumption)); + conn.SendPacket(new PowerSystemUpdateResponse(consumerRatio, generatorRatio, copyValues, generateCurrentTick, togglePower, powerGenRegister, powerConRegister, powerDisRegister, powerChaRegister, energyConsumption)); } } } diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs index 8b76bd080..c629e9bff 100644 --- a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs @@ -1,7 +1,10 @@ using NebulaAPI; +using NebulaModel.Logger; using NebulaModel.Networking; using NebulaModel.Packets; using NebulaModel.Packets.PowerSystem; +using NebulaWorld.Factory; +using System.Collections.Generic; namespace NebulaNetwork.PacketProcessors.PowerSystem { @@ -16,33 +19,79 @@ public override void ProcessPacket(PowerSystemUpdateResponse packet, NebulaConne } int pIndex = 0; - for(int i = 0; i < GameMain.localStar.planetCount; i++) + + for(int i = 0; i < GameMain.localStar?.planetCount; i++) { if(GameMain.localStar.planets[i]?.factory != null) { PlanetData pData = GameMain.localStar.planets[i]; global::PowerSystem pSys = pData.factory?.powerSystem; - if(pSys != null && pIndex < packet.EnergyCapacity.Length) + Log.Warn($"cl: {packet.ConsumerRatio.Length} ps on {pData.displayName} is {pSys != null} and factory is {pData.factory != null} ({i})"); + + if (pSys != null && pIndex < packet.ConsumerRatio.Length) { - if(pSys.netCursor != packet.EnergyCapacity[pIndex].Length) + if(pSys.netCursor != packet.ConsumerRatio[pIndex].Length) { + Log.Warn($"nc: {pSys.netCursor} len: {packet.ConsumerRatio[pIndex].Length}"); return; } - for(int j = 0; j < pSys.netCursor; j++) + Log.Warn($"nc: {pSys.netCursor}"); + + // netPool starts at index 1 but our array starts at index 0 :/ + for (int j = 0; j < pSys.netCursor - 1; j++) { - pSys.netPool[j].energyCapacity = packet.EnergyCapacity[pIndex][j]; - pSys.netPool[j].energyRequired = packet.EnergyRequired[pIndex][j]; - pSys.netPool[j].energyServed = packet.EnergyServed[pIndex][j]; - pSys.netPool[j].energyAccumulated = packet.EnergyAccumulated[pIndex][j]; - pSys.netPool[j].energyExchanged = packet.EnergyExchanged[pIndex][j]; - pSys.netPool[j].consumerRatio = packet.ConsumerRatio[pIndex][j]; + //pSys.netPool[j].energyCapacity = packet.EnergyCapacity[pIndex][j]; + //pSys.netPool[j].energyRequired = packet.EnergyRequired[pIndex][j]; + //pSys.netPool[j].energyServed = packet.EnergyServed[pIndex][j]; + //pSys.netPool[j].energyAccumulated = packet.EnergyAccumulated[pIndex][j]; + //pSys.netPool[j].energyExchanged = packet.EnergyExchanged[pIndex][j]; + pSys.netPool[j + 1].consumerRatio = packet.ConsumerRatio[pIndex][j]; + pSys.netPool[j + 1].generaterRatio = packet.GeneratorRatio[pIndex][j]; + if (packet.CopyValues[pIndex][j]) + { + pSys.networkServes[j] = (float)packet.ConsumerRatio[pIndex][j]; + pSys.networkGenerates[j] = (float)packet.GeneratorRatio[pIndex][j]; + } + else + { + pSys.networkServes[j] = 0f; + pSys.networkGenerates[j] = 0f; + } + + for(int k = 0; k < pSys.netPool[j + 1].generators.Count; k++) + { + pSys.genPool[pSys.netPool[j + 1].generators[k]].generateCurrentTick = packet.GenerateCurrentTick[pIndex][j]; + } + + if (PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pData.id, out var list)){ + if(list.Count > 0 && j < list.Count) + { + Log.Info($"adding {packet.TogglePower[pIndex][j]} to cache"); + list[j] = packet.TogglePower[pIndex][j] ? 1 : 0; + } + else + { + Log.Info("new list entry"); + list.Add(packet.TogglePower[pIndex][j] ? 1 : 0); + } + } + else + { + List newList = new List(); + newList.Add(packet.TogglePower[pIndex][j] ? 1 : 0); + + PowerSystemManager.PowerSystemAnimationCache.TryAdd(pData.id, newList); + } } + + pIndex++; } + /* FactoryProductionStat stats = GameMain.statistics.production.factoryStatPool[pData.factory.index]; - if(pIndex < packet.PowerGenRegister.Length) + if(i < packet.PowerGenRegister.Length) { lock (stats) { @@ -53,8 +102,7 @@ public override void ProcessPacket(PowerSystemUpdateResponse packet, NebulaConne stats.energyConsumption = packet.EnergyConsumption[pIndex]; } } - - pIndex++; + */ } } } diff --git a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs index 7c23c23d8..85a55a444 100644 --- a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs @@ -1,6 +1,9 @@ using HarmonyLib; +using NebulaModel.Logger; using NebulaModel.Packets.PowerSystem; using NebulaWorld; +using NebulaWorld.Factory; +using PowerNetworkStructures; using System.Collections.Generic; using UnityEngine; @@ -24,6 +27,8 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return false; } + UpdateAnimations(__instance, time); + timePassed += Time.deltaTime; if(timePassed >= REQUEST_INTERVAL) @@ -46,5 +51,124 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time } return true; } + + private static void UpdateAnimations(PowerSystem pSys, long time) + { + if(GameMain.localPlanet == null || GameMain.localPlanet.factory == null) + { + return; + } + + AnimData[] entityAnimPool = GameMain.localPlanet.factory.entityAnimPool; + float stepTime = 0.016666668f; + float speed = 1f; + + List animCache = null; + if(!PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pSys.planet.id, out animCache)) + { + // just too much spam + //Log.Warn($"Could not get PowerSystem animation cache, animations will be broken for planet {pSys.planet.displayName}!"); + } + + FactoryProductionStat factoryProductionStat = GameMain.statistics.production.factoryStatPool[pSys.factory.index]; + + bool useIonLayer = GameMain.history.useIonLayer; + bool useCata = time % 10L == 0L; + int[] productRegister = factoryProductionStat == null ? new int[0] : factoryProductionStat.productRegister; + int[] consumeRegister = factoryProductionStat == null ? new int[0] : factoryProductionStat.consumeRegister; + + Vector3 normalized = pSys.factory.planet.runtimeLocalSunDirection.normalized; + + foreach(PowerNetwork pNet in GameMain.localPlanet.factory.powerSystem.netPool) + { + if(pNet == null) + { + continue; + } + + for(int i = 0; i < pNet.generators.Count; i++) + { + // num35 taken from powerToggle (int the PowerSystemUpdateResponse packet) as it determines if num46 (generateCurrentTick) is 0 or computed based on the power net. + int eID = pSys.genPool[pNet.generators[i]].entityId; + long generateCurrentTick = animCache != null && animCache[pNet.id - 1] > 0 ? pSys.genPool[pNet.generators[i]].generateCurrentTick : 0; + //Log.Info($"{generateCurrentTick} in net {pNet.id} while cache is {animCache == null} and has {animCache?.Count} entries"); + + PrepareUpdateAnimations(pSys, pSys.genPool[pNet.generators[i]], normalized); + + if (pSys.genPool[pNet.generators[i]].wind) + { + // state is always enabled on wind as it seems, but with 0 windStrength it does not move anyways + speed = 0.7f; + entityAnimPool[eID].Step2(1U, stepTime, GameMain.localPlanet.windStrength, speed); + } + else if (pSys.genPool[pNet.generators[i]].gamma && factoryProductionStat != null) + { + pSys.genPool[pNet.generators[i]].GameTick_Gamma(useIonLayer, useCata, pSys.factory, productRegister, consumeRegister); + entityAnimPool[eID].time += stepTime; + + if(entityAnimPool[eID].time > 1f) + { + entityAnimPool[eID].time -= 1f; + } + + entityAnimPool[eID].power = (float)((double)pSys.genPool[pNet.generators[i]].capacityCurrentTick / (double)pSys.genPool[pNet.generators[i]].genEnergyPerTick); + entityAnimPool[eID].state = ((pSys.genPool[pNet.generators[i]].productId > 0) ? 2U : 0U) + ((pSys.genPool[pNet.generators[i]].catalystPoint > 0) ? 1U : 0U); + entityAnimPool[eID].working_length = entityAnimPool[eID].working_length * 0.99f + ((pSys.genPool[pNet.generators[i]].catalystPoint > 0) ? 0.01f : 0f); + } + else if(pSys.genPool[pNet.generators[i]].fuelMask > 1) + { + // updating power with approximate value, but its only used for animations client side so it should be fine + float power = (float)((double)entityAnimPool[eID].power * 0.98 + 0.02 * (double)((generateCurrentTick > 0L) ? 1 : 0)); + if(power > 0L) + { + speed = 2f; + } + if(generateCurrentTick > 0L && power < 0f) + { + power = 0f; + } + //Log.Warn(entityAnimPool[eID].power + " " + generateCurrentTick); + entityAnimPool[eID].Step2((entityAnimPool[eID].power > 0.1f || generateCurrentTick > 0L) ? 1U : 0U, stepTime, power, speed); + } + else + { + // updating power with approximate value, but its only used for animations client side so it should be fine + float power = (float)((double)entityAnimPool[eID].power * 0.98 + 0.02 * (double)generateCurrentTick / (double)pSys.genPool[pNet.generators[i]].genEnergyPerTick); + if (power > 0L) + { + speed = 2f; + } + if (generateCurrentTick > 0L && power < 0.2f) + { + power = 0.2f; + } + entityAnimPool[eID].Step2(((entityAnimPool[eID].power > 0.1f || generateCurrentTick > 0L)) ? 1U : 0U, stepTime, power, speed); + } + } + } + } + + // return num12 + private static void PrepareUpdateAnimations(PowerSystem pSys, PowerGeneratorComponent pComp, Vector3 normalized) + { + if (pComp.wind) + { + pComp.EnergyCap_Wind(pSys.factory.planet.windStrength); + } + else if (pComp.photovoltaic) + { + pComp.EnergyCap_PV(normalized.x, normalized.y, normalized.z, pSys.factory.planet.luminosity); + } + else if (pComp.gamma) + { + float response = (pSys.dysonSphere != null) ? pSys.dysonSphere.energyRespCoef : 0f; + pComp.EnergyCap_Gamma(response); + } + else + { + long output = pComp.EnergyCap_Fuel(); + pSys.factory.entitySignPool[pComp.entityId].signType = ((output > 30L) ? 0U : 8U); + } + } } } diff --git a/NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs index 829bd90a7..f9ffdefd0 100644 --- a/NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIPlanetDetail_Patch.cs @@ -58,10 +58,10 @@ public static bool _OnUpdate_Prefix(UIPlanetDetail __instance) [HarmonyPatch(nameof(UIPlanetDetail.RefreshDynamicProperties))] public static bool OnPlanetDataSet_Prefix(UIPlanetDetail __instance) { - if(Multiplayer.Session != null && Multiplayer.Session.IsInLobby) + if(BackupUniverseObserveLevel == -1 && Multiplayer.Session != null && Multiplayer.Session.IsInLobby) { BackupUniverseObserveLevel = GameMain.history.universeObserveLevel; - GameMain.history.universeObserveLevel = 3; + GameMain.history.universeObserveLevel = 4; } return true; } diff --git a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs index 2475e1f78..80c9bb970 100644 --- a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs +++ b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs @@ -1,15 +1,17 @@ using HarmonyLib; -using NebulaModel.Packets.Factory.PowerTower; using NebulaWorld; using System; using System.Collections.Generic; using System.Reflection.Emit; +using NebulaWorld.Factory; namespace NebulaPatcher.Patches.Transpilers { [HarmonyPatch(typeof(PowerSystem))] internal class PowerSystem_Transpiler { + public delegate void GetNum35(PowerSystem pSys, int netIndex, long num35); + [HarmonyTranspiler] [HarmonyPatch(nameof(PowerSystem.RequestDysonSpherePower))] public static IEnumerable PowerSystem_RequestDysonSpherePower_Transpiler(IEnumerable instructions) @@ -40,5 +42,66 @@ public static IEnumerable PowerSystem_RequestDysonSpherePower_T return instructions; } } + + /* + * we need num35 from the GameTick method to know if num46 stays at 0 or gets set to something. + * as num46 is very important to compute the power state (used for the animations) client side we need to cache num35 to serve it when requested by PowerSystemUpdateRequest + * num46 is generateCurrentTick + * JUST TRANSFER num46 asshead + */ + [HarmonyTranspiler] + [HarmonyPatch(nameof(PowerSystem.GameTick))] + public static IEnumerable PowerSystem_GameTick_Transpiler(IEnumerable instructions) + { + CodeMatcher matcher = new CodeMatcher(instructions) + .MatchForward(false, + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Sub), + new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNetwork), "energyCapacity")), + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PowerNetwork), "energyRequired")), + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Ldloc_S), + new CodeMatch(OpCodes.Add)); + + if (matcher.IsInvalid) + { + NebulaModel.Logger.Log.Error("PowerSystem.GameTick_Transpiler failed. Mod version not compatible with game version."); + return instructions; + } + + matcher + .InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0)) + .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 22)) + .InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 48)) + .Insert(HarmonyLib.Transpilers.EmitDelegate((PowerSystem pSys, int netIndex, long num35) => + { + if (PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pSys.planet.id, out var list)) + { + // netIndex starts at 1 + if(list.Count > 0 && netIndex - 1 < list.Count) + { + list[netIndex - 1] = num35; + } + else + { + list.Add(num35); + } + } + else + { + List newList = new List(); + newList.Add(num35); + + PowerSystemManager.PowerSystemAnimationCache.TryAdd(pSys.planet.id, newList); + } + })); + + return matcher.InstructionEnumeration(); + } } } diff --git a/NebulaWorld/Factory/PowerSystemManager.cs b/NebulaWorld/Factory/PowerSystemManager.cs new file mode 100644 index 000000000..cac82518d --- /dev/null +++ b/NebulaWorld/Factory/PowerSystemManager.cs @@ -0,0 +1,10 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace NebulaWorld.Factory +{ + public class PowerSystemManager + { + public static ConcurrentDictionary> PowerSystemAnimationCache = new ConcurrentDictionary>(); + } +} From 74be24f7a77cd6ebbd84bf34d0ff163ff251c89a Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Sat, 15 Jan 2022 23:11:58 +0100 Subject: [PATCH 5/9] compute generatCurrentTick clientside based on num35 and fix index out of bounds in cache usage --- .../PowerSystem/PowerSystemUpdateResponse.cs | 6 +- .../PowerSystemUpdateRequestProcessor.cs | 12 ++-- .../PowerSystemUpdateResponseProcessor.cs | 14 ++-- .../Patches/Dynamic/PowerSystem_Patch.cs | 64 ++++++++++++++++--- .../Transpilers/PowerSystem_Transpiler.cs | 2 +- 5 files changed, 71 insertions(+), 27 deletions(-) diff --git a/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs index 10ba86d3e..6a29673d4 100644 --- a/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs +++ b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs @@ -12,7 +12,7 @@ public class PowerSystemUpdateResponse public double[][] GeneratorRatio { get; set; } public bool[][] CopyValues { get; set; } public long[][] GenerateCurrentTick { get; set; } - public bool[][] TogglePower { get; set; } + public long[][] Num35 { get; set; } public long[] PowerGenRegister { get; set; } public long[] PowerConRegister { get; set; } public long[] PowerDisRegister { get; set; } @@ -28,7 +28,7 @@ public PowerSystemUpdateResponse(//long[][] energyCapacity, double[][] generatorRatio, bool[][] copyValues, long[][] generateCurrentTick, - bool[][] togglePower, + long[][] num35, long[] powerGenRegister, long[] powerConRegister, long[] powerDisRegister, @@ -44,7 +44,7 @@ public PowerSystemUpdateResponse(//long[][] energyCapacity, GeneratorRatio = generatorRatio; CopyValues = copyValues; GenerateCurrentTick = generateCurrentTick; - TogglePower = togglePower; + Num35 = num35; PowerGenRegister = powerGenRegister; PowerConRegister = powerConRegister; PowerDisRegister = powerDisRegister; diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs index f847ed1e4..1e7e4f03e 100644 --- a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs @@ -27,7 +27,7 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec double[][] generatorRatio = new double[packet.PlanetIDs.Length][]; bool[][] copyValues = new bool[packet.PlanetIDs.Length][]; long[][] generateCurrentTick = new long[packet.PlanetIDs.Length][]; - bool[][] togglePower = new bool[packet.PlanetIDs.Length][]; + long[][] num35 = new long[packet.PlanetIDs.Length][]; long[] powerGenRegister = new long[packet.PlanetIDs.Length]; long[] powerConRegister = new long[packet.PlanetIDs.Length]; long[] powerDisRegister = new long[packet.PlanetIDs.Length]; @@ -49,7 +49,7 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec generatorRatio[i] = new double[pSys.netCursor]; copyValues[i] = new bool[pSys.netCursor]; generateCurrentTick[i] = new long[pSys.netCursor]; - togglePower[i] = new bool[pSys.netCursor]; + num35[i] = new long[pSys.netCursor]; // netPool starts at index 1 but our array starts at index 0 :/ for(int j = 0; j < pSys.netCursor - 1; j++) @@ -73,11 +73,7 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec if (PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pData.id, out var list)) { - togglePower[i][j] = j < list.Count && list[j] > 0; - } - else - { - togglePower[i][j] = false; + num35[i][j] = j < list.Count ? list[j] : 0; } if((float)pSys.netPool[j + 1].consumerRatio == pSys.networkServes[j]) @@ -102,7 +98,7 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec } } - conn.SendPacket(new PowerSystemUpdateResponse(consumerRatio, generatorRatio, copyValues, generateCurrentTick, togglePower, powerGenRegister, powerConRegister, powerDisRegister, powerChaRegister, energyConsumption)); + conn.SendPacket(new PowerSystemUpdateResponse(consumerRatio, generatorRatio, copyValues, generateCurrentTick, num35, powerGenRegister, powerConRegister, powerDisRegister, powerChaRegister, energyConsumption)); } } } diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs index c629e9bff..c0521af41 100644 --- a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs @@ -60,27 +60,29 @@ public override void ProcessPacket(PowerSystemUpdateResponse packet, NebulaConne pSys.networkGenerates[j] = 0f; } + /* for(int k = 0; k < pSys.netPool[j + 1].generators.Count; k++) { pSys.genPool[pSys.netPool[j + 1].generators[k]].generateCurrentTick = packet.GenerateCurrentTick[pIndex][j]; } - + */ + if (PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pData.id, out var list)){ - if(list.Count > 0 && j < list.Count) + if (j < list.Count) { - Log.Info($"adding {packet.TogglePower[pIndex][j]} to cache"); - list[j] = packet.TogglePower[pIndex][j] ? 1 : 0; + Log.Info($"adding {packet.Num35[pIndex][j]} to cache"); + list[j] = packet.Num35[pIndex][j]; } else { Log.Info("new list entry"); - list.Add(packet.TogglePower[pIndex][j] ? 1 : 0); + list.Add(packet.Num35[pIndex][j]); } } else { List newList = new List(); - newList.Add(packet.TogglePower[pIndex][j] ? 1 : 0); + newList.Add(packet.Num35[pIndex][j]); PowerSystemManager.PowerSystemAnimationCache.TryAdd(pData.id, newList); } diff --git a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs index c32529f4d..47bc09e79 100644 --- a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs @@ -3,7 +3,6 @@ using NebulaModel.Packets.PowerSystem; using NebulaWorld; using NebulaWorld.Factory; -using PowerNetworkStructures; using System.Collections.Generic; using UnityEngine; @@ -33,6 +32,7 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return false; } + ComputeFuelUsage(__instance); UpdateAnimations(__instance, time); timePassed += Time.deltaTime; @@ -58,6 +58,56 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return true; } + private static void ComputeFuelUsage(PowerSystem pSys) + { + int[] consumeRegister = GameMain.statistics.production.factoryStatPool[pSys.factory.index].consumeRegister; + Vector3 normalized = pSys.factory.planet.runtimeLocalSunDirection.normalized; + + List animCache = null; + if (!PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pSys.planet.id, out animCache)) + { + // just too much spam + //Log.Warn($"Could not get PowerSystem animation cache, animations will be broken for planet {pSys.planet.displayName}!"); + } + + foreach (PowerNetwork pNet in pSys.netPool) + { + // pNets start at index 1 + if(pNet != null && animCache != null && pNet.id > 0 && pNet.id - 1 < animCache.Count) + { + //Log.Info($"{pNet.id} / {pSys.netCursor} | {animCache.Count}"); + long num35 = animCache[pNet.id - 1]; + + for (int i = 0; i < pNet.generators.Count; i++) + { + int cIndex = pNet.generators[i]; + long generateCurrentTick = 0L; + bool isPoweredByFuel = !pSys.genPool[cIndex].wind && !pSys.genPool[cIndex].photovoltaic && !pSys.genPool[cIndex].gamma; + + PrepareUpdateFuelComputation(pSys, ref pSys.genPool[cIndex], normalized); + if (isPoweredByFuel) + { + pSys.genPool[cIndex].currentStrength = (float)((num35 > 0L && pSys.genPool[cIndex].capacityCurrentTick > 0L) ? 1 : 0); + } + if(num35 > 0L && pSys.genPool[cIndex].productId == 0) + { + long energy = (long)(pNet.generaterRatio * (double)pSys.genPool[cIndex].capacityCurrentTick + 0.99999); + generateCurrentTick = ((num35 < energy) ? num35 : energy); + if(generateCurrentTick > 0L) + { + num35 -= generateCurrentTick; + if (isPoweredByFuel) + { + pSys.genPool[cIndex].GenEnergyByFuel(generateCurrentTick, consumeRegister); + } + pSys.genPool[cIndex].generateCurrentTick = generateCurrentTick; // wey we can compute num46 from num35!! + } + } + } + } + } + } + private static void UpdateAnimations(PowerSystem pSys, long time) { if(GameMain.localPlanet == null || GameMain.localPlanet.factory == null) @@ -83,24 +133,20 @@ private static void UpdateAnimations(PowerSystem pSys, long time) int[] productRegister = factoryProductionStat == null ? new int[0] : factoryProductionStat.productRegister; int[] consumeRegister = factoryProductionStat == null ? new int[0] : factoryProductionStat.consumeRegister; - Vector3 normalized = pSys.factory.planet.runtimeLocalSunDirection.normalized; - foreach(PowerNetwork pNet in GameMain.localPlanet.factory.powerSystem.netPool) { - if(pNet == null) + if(pNet == null || animCache == null) { continue; } - for(int i = 0; i < pNet.generators.Count; i++) + for(int i = 0; i < pNet.generators.Count && pNet.id - 1 < animCache.Count; i++) { // num35 taken from powerToggle (int the PowerSystemUpdateResponse packet) as it determines if num46 (generateCurrentTick) is 0 or computed based on the power net. int eID = pSys.genPool[pNet.generators[i]].entityId; - long generateCurrentTick = animCache != null && animCache[pNet.id - 1] > 0 ? pSys.genPool[pNet.generators[i]].generateCurrentTick : 0; + long generateCurrentTick = animCache[pNet.id - 1] > 0 ? pSys.genPool[pNet.generators[i]].generateCurrentTick : 0; //Log.Info($"{generateCurrentTick} in net {pNet.id} while cache is {animCache == null} and has {animCache?.Count} entries"); - PrepareUpdateAnimations(pSys, pSys.genPool[pNet.generators[i]], normalized); - if (pSys.genPool[pNet.generators[i]].wind) { // state is always enabled on wind as it seems, but with 0 windStrength it does not move anyways @@ -155,7 +201,7 @@ private static void UpdateAnimations(PowerSystem pSys, long time) } // return num12 - private static void PrepareUpdateAnimations(PowerSystem pSys, PowerGeneratorComponent pComp, Vector3 normalized) + private static void PrepareUpdateFuelComputation(PowerSystem pSys, ref PowerGeneratorComponent pComp, Vector3 normalized) { if (pComp.wind) { diff --git a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs index 80c9bb970..df6da68b1 100644 --- a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs +++ b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs @@ -83,7 +83,7 @@ public static IEnumerable PowerSystem_GameTick_Transpiler(IEnum if (PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pSys.planet.id, out var list)) { // netIndex starts at 1 - if(list.Count > 0 && netIndex - 1 < list.Count) + if(netIndex - 1 < list.Count) { list[netIndex - 1] = num35; } From bb50c8a64ffbc2f8113a921df4a48ebdbc12bee4 Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Sun, 16 Jan 2022 19:50:21 +0100 Subject: [PATCH 6/9] add client side check if facility has enough energy to be powered and turn off animation if needed. --- .../Patches/Dynamic/PowerSystem_Patch.cs | 112 +++++++----------- 1 file changed, 44 insertions(+), 68 deletions(-) diff --git a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs index 47bc09e79..1d8402435 100644 --- a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs @@ -32,7 +32,6 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return false; } - ComputeFuelUsage(__instance); UpdateAnimations(__instance, time); timePassed += Time.deltaTime; @@ -58,56 +57,6 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return true; } - private static void ComputeFuelUsage(PowerSystem pSys) - { - int[] consumeRegister = GameMain.statistics.production.factoryStatPool[pSys.factory.index].consumeRegister; - Vector3 normalized = pSys.factory.planet.runtimeLocalSunDirection.normalized; - - List animCache = null; - if (!PowerSystemManager.PowerSystemAnimationCache.TryGetValue(pSys.planet.id, out animCache)) - { - // just too much spam - //Log.Warn($"Could not get PowerSystem animation cache, animations will be broken for planet {pSys.planet.displayName}!"); - } - - foreach (PowerNetwork pNet in pSys.netPool) - { - // pNets start at index 1 - if(pNet != null && animCache != null && pNet.id > 0 && pNet.id - 1 < animCache.Count) - { - //Log.Info($"{pNet.id} / {pSys.netCursor} | {animCache.Count}"); - long num35 = animCache[pNet.id - 1]; - - for (int i = 0; i < pNet.generators.Count; i++) - { - int cIndex = pNet.generators[i]; - long generateCurrentTick = 0L; - bool isPoweredByFuel = !pSys.genPool[cIndex].wind && !pSys.genPool[cIndex].photovoltaic && !pSys.genPool[cIndex].gamma; - - PrepareUpdateFuelComputation(pSys, ref pSys.genPool[cIndex], normalized); - if (isPoweredByFuel) - { - pSys.genPool[cIndex].currentStrength = (float)((num35 > 0L && pSys.genPool[cIndex].capacityCurrentTick > 0L) ? 1 : 0); - } - if(num35 > 0L && pSys.genPool[cIndex].productId == 0) - { - long energy = (long)(pNet.generaterRatio * (double)pSys.genPool[cIndex].capacityCurrentTick + 0.99999); - generateCurrentTick = ((num35 < energy) ? num35 : energy); - if(generateCurrentTick > 0L) - { - num35 -= generateCurrentTick; - if (isPoweredByFuel) - { - pSys.genPool[cIndex].GenEnergyByFuel(generateCurrentTick, consumeRegister); - } - pSys.genPool[cIndex].generateCurrentTick = generateCurrentTick; // wey we can compute num46 from num35!! - } - } - } - } - } - } - private static void UpdateAnimations(PowerSystem pSys, long time) { if(GameMain.localPlanet == null || GameMain.localPlanet.factory == null) @@ -132,30 +81,57 @@ private static void UpdateAnimations(PowerSystem pSys, long time) bool useCata = time % 10L == 0L; int[] productRegister = factoryProductionStat == null ? new int[0] : factoryProductionStat.productRegister; int[] consumeRegister = factoryProductionStat == null ? new int[0] : factoryProductionStat.consumeRegister; + Vector3 normalized = pSys.factory.planet.runtimeLocalSunDirection.normalized; - foreach(PowerNetwork pNet in GameMain.localPlanet.factory.powerSystem.netPool) + foreach (PowerNetwork pNet in GameMain.localPlanet.factory.powerSystem.netPool) { if(pNet == null || animCache == null) { continue; } - for(int i = 0; i < pNet.generators.Count && pNet.id - 1 < animCache.Count; i++) + for (int i = 0; i < pNet.generators.Count && pNet.id - 1 < animCache.Count; i++) { - // num35 taken from powerToggle (int the PowerSystemUpdateResponse packet) as it determines if num46 (generateCurrentTick) is 0 or computed based on the power net. - int eID = pSys.genPool[pNet.generators[i]].entityId; - long generateCurrentTick = animCache[pNet.id - 1] > 0 ? pSys.genPool[pNet.generators[i]].generateCurrentTick : 0; + int compIndex = pNet.generators[i]; + int eID = pSys.genPool[compIndex].entityId; + + long num35 = animCache[pNet.id - 1]; + + bool isPoweredByFuel = !pSys.genPool[compIndex].wind && !pSys.genPool[compIndex].photovoltaic && !pSys.genPool[compIndex].gamma; + long generateCurrentTick = num35 > 0 ? pSys.genPool[compIndex].generateCurrentTick : 0; //Log.Info($"{generateCurrentTick} in net {pNet.id} while cache is {animCache == null} and has {animCache?.Count} entries"); - if (pSys.genPool[pNet.generators[i]].wind) + // first compute fuel usage and energy left in facility. Also compute generateCurrentTick as its different for each facility but based on num35 which we sync in the animCache. + PrepareUpdateFuelComputation(pSys, ref pSys.genPool[compIndex], normalized); + if (isPoweredByFuel) + { + pSys.genPool[compIndex].currentStrength = (float)((num35 > 0L && pSys.genPool[compIndex].capacityCurrentTick > 0L) ? 1 : 0); + } + if (num35 > 0L && pSys.genPool[compIndex].productId == 0) + { + long energy = (long)(pNet.generaterRatio * (double)pSys.genPool[compIndex].capacityCurrentTick + 0.99999); + generateCurrentTick = ((num35 < energy) ? num35 : energy); + if (generateCurrentTick > 0L) + { + num35 -= generateCurrentTick; + if (isPoweredByFuel) + { + pSys.genPool[compIndex].GenEnergyByFuel(generateCurrentTick, consumeRegister); + } + pSys.genPool[compIndex].generateCurrentTick = generateCurrentTick; // wey we can compute num46 from num35!! + } + } + + // then update animation status based on the current energy + if (pSys.genPool[compIndex].wind) { // state is always enabled on wind as it seems, but with 0 windStrength it does not move anyways speed = 0.7f; entityAnimPool[eID].Step2(1U, stepTime, GameMain.localPlanet.windStrength, speed); } - else if (pSys.genPool[pNet.generators[i]].gamma && factoryProductionStat != null) + else if (pSys.genPool[compIndex].gamma && factoryProductionStat != null) { - pSys.genPool[pNet.generators[i]].GameTick_Gamma(useIonLayer, useCata, pSys.factory, productRegister, consumeRegister); + pSys.genPool[compIndex].GameTick_Gamma(useIonLayer, useCata, pSys.factory, productRegister, consumeRegister); entityAnimPool[eID].time += stepTime; if(entityAnimPool[eID].time > 1f) @@ -163,14 +139,14 @@ private static void UpdateAnimations(PowerSystem pSys, long time) entityAnimPool[eID].time -= 1f; } - entityAnimPool[eID].power = (float)((double)pSys.genPool[pNet.generators[i]].capacityCurrentTick / (double)pSys.genPool[pNet.generators[i]].genEnergyPerTick); - entityAnimPool[eID].state = ((pSys.genPool[pNet.generators[i]].productId > 0) ? 2U : 0U) + ((pSys.genPool[pNet.generators[i]].catalystPoint > 0) ? 1U : 0U); - entityAnimPool[eID].working_length = entityAnimPool[eID].working_length * 0.99f + ((pSys.genPool[pNet.generators[i]].catalystPoint > 0) ? 0.01f : 0f); + entityAnimPool[eID].power = (float)((double)pSys.genPool[compIndex].capacityCurrentTick / (double)pSys.genPool[compIndex].genEnergyPerTick); + entityAnimPool[eID].state = ((pSys.genPool[compIndex].productId > 0) ? 2U : 0U) + ((pSys.genPool[compIndex].catalystPoint > 0) ? 1U : 0U); + entityAnimPool[eID].working_length = entityAnimPool[eID].working_length * 0.99f + ((pSys.genPool[compIndex].catalystPoint > 0) ? 0.01f : 0f); } else if(pSys.genPool[pNet.generators[i]].fuelMask > 1) { - // updating power with approximate value, but its only used for animations client side so it should be fine - float power = (float)((double)entityAnimPool[eID].power * 0.98 + 0.02 * (double)((generateCurrentTick > 0L) ? 1 : 0)); + // capacityCurrentTick is > 30 when there is still fuel energy inside the facility (check needed to turn off animations when fuel runs out) + float power = (float)((double)entityAnimPool[eID].power * 0.98 + 0.02 * (double)((generateCurrentTick > 0L && pSys.genPool[compIndex].capacityCurrentTick > 30L) ? 1 : 0)); if(power > 0L) { speed = 2f; @@ -184,8 +160,8 @@ private static void UpdateAnimations(PowerSystem pSys, long time) } else { - // updating power with approximate value, but its only used for animations client side so it should be fine - float power = (float)((double)entityAnimPool[eID].power * 0.98 + 0.02 * (double)generateCurrentTick / (double)pSys.genPool[pNet.generators[i]].genEnergyPerTick); + // capacityCurrentTick is > 30 when there is still fuel energy inside the facility (check needed to turn off animations when fuel runs out) + float power = (float)((double)entityAnimPool[eID].power * 0.98 + 0.02 * (double)generateCurrentTick / (double)pSys.genPool[compIndex].genEnergyPerTick); if (power > 0L) { speed = 2f; @@ -194,13 +170,13 @@ private static void UpdateAnimations(PowerSystem pSys, long time) { power = 0.2f; } - entityAnimPool[eID].Step2(((entityAnimPool[eID].power > 0.1f || generateCurrentTick > 0L)) ? 1U : 0U, stepTime, power, speed); + entityAnimPool[eID].Step2(((entityAnimPool[eID].power > 0.1f || (generateCurrentTick > 0L && pSys.genPool[compIndex].capacityCurrentTick > 30L))) ? 1U : 0U, stepTime, power, speed); } } } } - // return num12 + // compute capacityCurrentTick private static void PrepareUpdateFuelComputation(PowerSystem pSys, ref PowerGeneratorComponent pComp, Vector3 normalized) { if (pComp.wind) From 6b056e6439c48083459a508a2190cd193d9bd1f6 Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Sun, 16 Jan 2022 23:14:19 +0100 Subject: [PATCH 7/9] compute sign pool client side --- .../Patches/Dynamic/PowerSystem_Patch.cs | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs index 1d8402435..d0e3c112c 100644 --- a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs @@ -32,7 +32,7 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return false; } - UpdateAnimations(__instance, time); + UpdateAnimations(__instance, time, isActive); timePassed += Time.deltaTime; @@ -57,7 +57,7 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return true; } - private static void UpdateAnimations(PowerSystem pSys, long time) + private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive) { if(GameMain.localPlanet == null || GameMain.localPlanet.factory == null) { @@ -83,10 +83,17 @@ private static void UpdateAnimations(PowerSystem pSys, long time) int[] consumeRegister = factoryProductionStat == null ? new int[0] : factoryProductionStat.consumeRegister; Vector3 normalized = pSys.factory.planet.runtimeLocalSunDirection.normalized; + SignData[] entitySignPool = pSys.factory.entitySignPool; + foreach (PowerNetwork pNet in GameMain.localPlanet.factory.powerSystem.netPool) { if(pNet == null || animCache == null) { + if(pNet != null && animCache == null) + { + // still update signs even if there is no power source on this planet + UpdateSignPool(pSys, entitySignPool, pNet, ref isActive); + } continue; } @@ -173,6 +180,44 @@ private static void UpdateAnimations(PowerSystem pSys, long time) entityAnimPool[eID].Step2(((entityAnimPool[eID].power > 0.1f || (generateCurrentTick > 0L && pSys.genPool[compIndex].capacityCurrentTick > 30L))) ? 1U : 0U, stepTime, power, speed); } } + + UpdateSignPool(pSys, entitySignPool, pNet, ref isActive); + } + } + + private static void UpdateSignPool(PowerSystem pSys, SignData[] entitySignPool, PowerNetwork pNet, ref bool isActive) + { + if (isActive) + { + List consumers = pNet.consumers; + if (pNet.id == 0) + { + for (int i = 0; i < pNet.consumers.Count; i++) + { + entitySignPool[pSys.consumerPool[consumers[i]].entityId].signType = 1U; + } + } + else if (pNet.consumerRatio < 0.10000000149011612) + { + for (int i = 0; i < pNet.consumers.Count; i++) + { + entitySignPool[pSys.consumerPool[consumers[i]].entityId].signType = 2U; + } + } + else if (pNet.consumerRatio < 0.5) + { + for (int i = 0; i < pNet.consumers.Count; i++) + { + entitySignPool[pSys.consumerPool[consumers[i]].entityId].signType = 3U; + } + } + else + { + for (int i = 0; i < pNet.consumers.Count; i++) + { + entitySignPool[pSys.consumerPool[consumers[i]].entityId].signType = 0U; + } + } } } From 2c862783b8f5403e2faf060999ed45b46af58e79 Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Mon, 17 Jan 2022 08:45:32 +0100 Subject: [PATCH 8/9] fix index error resulting in network id missmatch --- .../PowerSystem/PowerSystemUpdateRequestProcessor.cs | 2 +- .../PowerSystem/PowerSystemUpdateResponseProcessor.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs index 1e7e4f03e..be236b537 100644 --- a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs @@ -76,7 +76,7 @@ public override void ProcessPacket(PowerSystemUpdateRequest packet, NebulaConnec num35[i][j] = j < list.Count ? list[j] : 0; } - if((float)pSys.netPool[j + 1].consumerRatio == pSys.networkServes[j]) + if((float)pSys.netPool[j + 1].consumerRatio == pSys.networkServes[j + 1]) { copyValues[i][j] = true; } diff --git a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs index c0521af41..af60e2852 100644 --- a/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs @@ -51,13 +51,13 @@ public override void ProcessPacket(PowerSystemUpdateResponse packet, NebulaConne pSys.netPool[j + 1].generaterRatio = packet.GeneratorRatio[pIndex][j]; if (packet.CopyValues[pIndex][j]) { - pSys.networkServes[j] = (float)packet.ConsumerRatio[pIndex][j]; - pSys.networkGenerates[j] = (float)packet.GeneratorRatio[pIndex][j]; + pSys.networkServes[j + 1] = (float)packet.ConsumerRatio[pIndex][j]; + pSys.networkGenerates[j + 1] = (float)packet.GeneratorRatio[pIndex][j]; } else { - pSys.networkServes[j] = 0f; - pSys.networkGenerates[j] = 0f; + pSys.networkServes[j + 1] = 0f; + pSys.networkGenerates[j + 1] = 0f; } /* From b0e6ea4d8227baaab4383e92db29a7ac8b5ef1b7 Mon Sep 17 00:00:00 2001 From: sp00ktober Date: Thu, 20 Jan 2022 22:20:22 +0100 Subject: [PATCH 9/9] started to work on wireless towers and tesla towers --- .../Patches/Dynamic/PowerSystem_Patch.cs | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs index d0e3c112c..e33d5ff1f 100644 --- a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs @@ -3,6 +3,7 @@ using NebulaModel.Packets.PowerSystem; using NebulaWorld; using NebulaWorld.Factory; +using PowerNetworkStructures; using System.Collections.Generic; using UnityEngine; @@ -32,7 +33,7 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return false; } - UpdateAnimations(__instance, time, isActive); + UpdateAnimations(__instance, time, isActive, isMultithreadMode); timePassed += Time.deltaTime; @@ -57,7 +58,7 @@ public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time return true; } - private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive) + private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive, bool isMultiplayerMode) { if(GameMain.localPlanet == null || GameMain.localPlanet.factory == null) { @@ -85,6 +86,17 @@ private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive) SignData[] entitySignPool = pSys.factory.entitySignPool; + Vector3 playerPos = Vector3.zero; + bool triggerPlayerRecharge = GameMain.mainPlayer.mecha.coreEnergyCap - GameMain.mainPlayer.mecha.coreEnergy > 10000.0; + if(triggerPlayerRecharge && GameMain.mainPlayer.planetId == pSys.planet.id) + { + playerPos = (isMultiplayerMode ? pSys.multithreadPlayerPos : GameMain.mainPlayer.position); + } + else + { + triggerPlayerRecharge = false; + } + foreach (PowerNetwork pNet in GameMain.localPlanet.factory.powerSystem.netPool) { if(pNet == null || animCache == null) @@ -93,10 +105,14 @@ private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive) { // still update signs even if there is no power source on this planet UpdateSignPool(pSys, entitySignPool, pNet, ref isActive); + // still compute wireless charger state + ComputeWirelessChargerState(pSys, pNet, triggerPlayerRecharge, playerPos); } continue; } + ComputeWirelessChargerState(pSys, pNet, triggerPlayerRecharge, playerPos); + for (int i = 0; i < pNet.generators.Count && pNet.id - 1 < animCache.Count; i++) { int compIndex = pNet.generators[i]; @@ -106,7 +122,6 @@ private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive) bool isPoweredByFuel = !pSys.genPool[compIndex].wind && !pSys.genPool[compIndex].photovoltaic && !pSys.genPool[compIndex].gamma; long generateCurrentTick = num35 > 0 ? pSys.genPool[compIndex].generateCurrentTick : 0; - //Log.Info($"{generateCurrentTick} in net {pNet.id} while cache is {animCache == null} and has {animCache?.Count} entries"); // first compute fuel usage and energy left in facility. Also compute generateCurrentTick as its different for each facility but based on num35 which we sync in the animCache. PrepareUpdateFuelComputation(pSys, ref pSys.genPool[compIndex], normalized); @@ -152,7 +167,6 @@ private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive) } else if(pSys.genPool[pNet.generators[i]].fuelMask > 1) { - // capacityCurrentTick is > 30 when there is still fuel energy inside the facility (check needed to turn off animations when fuel runs out) float power = (float)((double)entityAnimPool[eID].power * 0.98 + 0.02 * (double)((generateCurrentTick > 0L && pSys.genPool[compIndex].capacityCurrentTick > 30L) ? 1 : 0)); if(power > 0L) { @@ -162,7 +176,7 @@ private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive) { power = 0f; } - //Log.Warn(entityAnimPool[eID].power + " " + generateCurrentTick); + entityAnimPool[eID].Step2((entityAnimPool[eID].power > 0.1f || generateCurrentTick > 0L) ? 1U : 0U, stepTime, power, speed); } else @@ -185,6 +199,47 @@ private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive) } } + // use requiredEnergy to determine the animation state further down in the UpdateAnimations() method + private static void ComputeWirelessChargerState(PowerSystem pSys, PowerNetwork pNet, bool triggerPlayerRecharge, Vector3 playerPos) + { + foreach(Node node in pNet.nodes) + { + int id = node.id; + if(pSys.nodePool[id].id == id && pSys.nodePool[id].isCharger){ + if (triggerPlayerRecharge) + { + float num8 = pSys.nodePool[id].powerPoint.x * 0.988f - playerPos.x; + float num9 = pSys.nodePool[id].powerPoint.y * 0.988f - playerPos.y; + float num10 = pSys.nodePool[id].powerPoint.z * 0.988f - playerPos.z; + if(pSys.nodePool[id].coverRadius < 15f && (double)(num8 * num8 + num9 * num9 + num10 * num10) <= 64.05) + { + if(pSys.nodePool[id].requiredEnergy == pSys.nodePool[id].idleEnergyPerTick) + { + // tower starts to work, send event to host + } + pSys.nodePool[id].requiredEnergy = pSys.nodePool[id].workEnergyPerTick; + } + else + { + if(pSys.nodePool[id].requiredEnergy == pSys.nodePool[id].workEnergyPerTick) + { + // tower stops to work, send event to host + } + pSys.nodePool[id].requiredEnergy = pSys.nodePool[id].idleEnergyPerTick; + } + } + else + { + if(pSys.nodePool[id].requiredEnergy == pSys.nodePool[id].workEnergyPerTick) + { + // tower stops to work, send event to host + } + pSys.nodePool[id].requiredEnergy = pSys.nodePool[id].idleEnergyPerTick; + } + } + } + } + private static void UpdateSignPool(PowerSystem pSys, SignData[] entitySignPool, PowerNetwork pNet, ref bool isActive) { if (isActive)