diff --git a/NebulaModel/Networking/Serialization/NetSerializer.cs b/NebulaModel/Networking/Serialization/NetSerializer.cs index 661fda66d..86d6b9cdc 100644 --- a/NebulaModel/Networking/Serialization/NetSerializer.cs +++ b/NebulaModel/Networking/Serialization/NetSerializer.cs @@ -469,6 +469,84 @@ 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 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; @@ -637,7 +715,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[]) && elementType != typeof(bool[])) ? CallType.Array : CallType.Basic; if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>)) { @@ -657,17 +736,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 +755,85 @@ 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 if(elementType == typeof(bool[])) // handles bool[][] + { + serializer = new Bool2ArraySerializer(); } 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/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..6a29673d4 --- /dev/null +++ b/NebulaModel/Packets/PowerSystem/PowerSystemUpdateResponse.cs @@ -0,0 +1,55 @@ +namespace NebulaModel.Packets.PowerSystem +{ + 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 double[][] ConsumerRatio { get; set; } + public double[][] GeneratorRatio { get; set; } + public bool[][] CopyValues { get; set; } + public long[][] GenerateCurrentTick { get; set; } + public long[][] Num35 { 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, + double[][] consumerRatio, + double[][] generatorRatio, + bool[][] copyValues, + long[][] generateCurrentTick, + long[][] num35, + long[] powerGenRegister, + long[] powerConRegister, + long[] powerDisRegister, + long[] powerChaRegister, + long[] energyConsumption) + { + //EnergyCapacity = energyCapacity; + //EnergyRequired = energyRequired; + //EnergyServed = energyServed; + //EnergyAccumulated = energyAccumulated; + //EnergyExchanged = energyExchanged; + ConsumerRatio = consumerRatio; + GeneratorRatio = generatorRatio; + CopyValues = copyValues; + GenerateCurrentTick = generateCurrentTick; + Num35 = num35; + 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..be236b537 --- /dev/null +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateRequestProcessor.cs @@ -0,0 +1,104 @@ +using NebulaAPI; +using NebulaModel.Logger; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.PowerSystem; +using NebulaWorld.Factory; + +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 + //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][]; + 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]; + 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) + { + //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]; + 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++) + { + //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)) + { + num35[i][j] = j < list.Count ? list[j] : 0; + } + + if((float)pSys.netPool[j + 1].consumerRatio == pSys.networkServes[j + 1]) + { + copyValues[i][j] = true; + } + else + { + copyValues[i][j] = false; + } + } + + 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(consumerRatio, generatorRatio, copyValues, generateCurrentTick, num35, 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..af60e2852 --- /dev/null +++ b/NebulaNetwork/PacketProcessors/PowerSystem/PowerSystemUpdateResponseProcessor.cs @@ -0,0 +1,113 @@ +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 +{ + [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; + + 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.ConsumerRatio[pIndex].Length) + { + Log.Warn($"nc: {pSys.netCursor} len: {packet.ConsumerRatio[pIndex].Length}"); + return; + } + + 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 + 1].consumerRatio = packet.ConsumerRatio[pIndex][j]; + pSys.netPool[j + 1].generaterRatio = packet.GeneratorRatio[pIndex][j]; + if (packet.CopyValues[pIndex][j]) + { + pSys.networkServes[j + 1] = (float)packet.ConsumerRatio[pIndex][j]; + pSys.networkGenerates[j + 1] = (float)packet.GeneratorRatio[pIndex][j]; + } + else + { + pSys.networkServes[j + 1] = 0f; + pSys.networkGenerates[j + 1] = 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 (j < list.Count) + { + Log.Info($"adding {packet.Num35[pIndex][j]} to cache"); + list[j] = packet.Num35[pIndex][j]; + } + else + { + Log.Info("new list entry"); + list.Add(packet.Num35[pIndex][j]); + } + } + else + { + List newList = new List(); + newList.Add(packet.Num35[pIndex][j]); + + PowerSystemManager.PowerSystemAnimationCache.TryAdd(pData.id, newList); + } + } + + pIndex++; + } + + /* + FactoryProductionStat stats = GameMain.statistics.production.factoryStatPool[pData.factory.index]; + if(i < packet.PowerGenRegister.Length) + { + 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]; + } + } + */ + } + } + } + } +} + diff --git a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs index 0fa331dee..e33d5ff1f 100644 --- a/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PowerSystem_Patch.cs @@ -1,51 +1,302 @@ using HarmonyLib; +using NebulaModel.Logger; +using NebulaModel.Packets.PowerSystem; using NebulaWorld; +using NebulaWorld.Factory; +using PowerNetworkStructures; +using System.Collections.Generic; +using UnityEngine; namespace NebulaPatcher.Patches.Dynamic { [HarmonyPatch(typeof(PowerSystem))] internal class PowerSystem_Patch { + private const float REQUEST_INTERVAL = 1; + private static float timePassed; + [HarmonyPrefix] [HarmonyPatch(nameof(PowerSystem.GameTick))] - public static void PowerSystem_GameTick_Prefix(long time, ref bool isActive) + public static bool PowerSystem_GameTick_Prefix(PowerSystem __instance, long time, ref bool isActive, bool isMultithreadMode) { //Enable signType update on remote planet every 64 tick if ((time & 63) == 0 && Multiplayer.IsActive && Multiplayer.Session.LocalPlayer.IsHost) { isActive |= true; } + + if (Multiplayer.IsActive && Multiplayer.Session.LocalPlayer.IsClient) + { + // if player is not in a solar system he has no factories loaded, thus nothing to sync here + if(GameMain.localStar == null) + { + return false; + } + + UpdateAnimations(__instance, time, isActive, isMultithreadMode); + + 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; } - [HarmonyPostfix] - [HarmonyPatch(nameof(PowerSystem.GameTick))] - public static void PowerSystem_GameTick_Postfix(PowerSystem __instance, long time, bool isActive, bool isMultithreadMode) + private static void UpdateAnimations(PowerSystem pSys, long time, bool isActive, bool isMultiplayerMode) { - if (Multiplayer.IsActive) + 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; + + 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) { - for (int i = 1; i < __instance.netCursor; i++) + playerPos = (isMultiplayerMode ? pSys.multithreadPlayerPos : GameMain.mainPlayer.position); + } + else + { + triggerPlayerRecharge = false; + } + + 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); + // 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++) { - PowerNetwork pNet = __instance.netPool[i]; - pNet.energyRequired += Multiplayer.Session.PowerTowers.GetExtraDemand(__instance.planet.id, i); + 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; + + // 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[compIndex].gamma && factoryProductionStat != null) + { + pSys.genPool[compIndex].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[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) + { + 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; + } + if(generateCurrentTick > 0L && power < 0f) + { + power = 0f; + } + + entityAnimPool[eID].Step2((entityAnimPool[eID].power > 0.1f || generateCurrentTick > 0L) ? 1U : 0U, stepTime, power, speed); + } + else + { + // 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; + } + if (generateCurrentTick > 0L && power < 0.2f) + { + power = 0.2f; + } + entityAnimPool[eID].Step2(((entityAnimPool[eID].power > 0.1f || (generateCurrentTick > 0L && pSys.genPool[compIndex].capacityCurrentTick > 30L))) ? 1U : 0U, stepTime, power, speed); + } } - Multiplayer.Session.PowerTowers.GivePlayerPower(); - Multiplayer.Session.PowerTowers.UpdateAllAnimations(__instance.planet.id); + + UpdateSignPool(pSys, entitySignPool, pNet, ref isActive); } } - [HarmonyPrefix] - [HarmonyPatch(nameof(PowerSystem.RemoveNodeComponent))] - public static bool RemoveNodeComponent(PowerSystem __instance, int id) + // 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) { - if (Multiplayer.IsActive) + foreach(Node node in pNet.nodes) { - // 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); + 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; + } + } } + } - return true; + 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; + } + } + } + } + + // compute capacityCurrentTick + private static void PrepareUpdateFuelComputation(PowerSystem pSys, ref 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/Transpilers/PowerSystem_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs index 3cbbd6d73..df6da68b1 100644 --- a/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs +++ b/NebulaPatcher/Patches/Transpilers/PowerSystem_Transpiler.cs @@ -1,132 +1,16 @@ 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 { - 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(); - } + public delegate void GetNum35(PowerSystem pSys, int netIndex, long num35); [HarmonyTranspiler] [HarmonyPatch(nameof(PowerSystem.RequestDysonSpherePower))] @@ -158,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(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>(); + } +} 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 05bd574dd..168208f5e 100644 --- a/NebulaWorld/MultiplayerSession.cs +++ b/NebulaWorld/MultiplayerSession.cs @@ -21,7 +21,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; } @@ -61,7 +60,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(); @@ -93,9 +91,6 @@ public void Dispose() Storage?.Dispose(); Storage = null; - PowerTowers?.Dispose(); - PowerTowers = null; - Belts?.Dispose(); Belts = null;