diff --git a/NebulaClient/PacketProcessors/Factory/Entity/BuildEntityRequestProcessor.cs b/NebulaClient/PacketProcessors/Factory/Entity/BuildEntityRequestProcessor.cs index c03672bee..22d688d92 100644 --- a/NebulaClient/PacketProcessors/Factory/Entity/BuildEntityRequestProcessor.cs +++ b/NebulaClient/PacketProcessors/Factory/Entity/BuildEntityRequestProcessor.cs @@ -1,8 +1,10 @@ using NebulaModel.Attributes; +using NebulaModel.Logger; using NebulaModel.Networking; using NebulaModel.Packets.Factory; using NebulaModel.Packets.Processors; using NebulaWorld.Factory; +using NebulaWorld.Player; namespace NebulaClient.PacketProcessors.Factory.Entity { @@ -31,6 +33,13 @@ public void ProcessPacket(BuildEntityRequest packet, NebulaConnection conn) planet.audio.Init(); } + //Remove building from drone queue + GameMain.mainPlayer.mecha.droneLogic.serving.Remove(-packet.PrebuildId); + planet.factory.BuildFinally(GameMain.mainPlayer, packet.PrebuildId); + if (!DroneManager.RemoveBuildRequest(-packet.PrebuildId)) + { + Log.Warn($"Build Request was not succesfully removed."); + } planet.factory.BuildFinally(GameMain.mainPlayer, packet.PrebuildId); // Make sure to free the physics once the FlattenTerrain is done diff --git a/NebulaHost/PacketProcessors/Factory/Entity/BuildEntityRequestProcessor.cs b/NebulaHost/PacketProcessors/Factory/Entity/BuildEntityRequestProcessor.cs index d1586e5a1..db938da42 100644 --- a/NebulaHost/PacketProcessors/Factory/Entity/BuildEntityRequestProcessor.cs +++ b/NebulaHost/PacketProcessors/Factory/Entity/BuildEntityRequestProcessor.cs @@ -40,6 +40,8 @@ public void ProcessPacket(BuildEntityRequest packet, NebulaConnection conn) } } + //Remove building from drone queue + GameMain.mainPlayer.mecha.droneLogic.serving.Remove(-packet.PrebuildId); planet.factory.BuildFinally(GameMain.mainPlayer, packet.PrebuildId); // Make sure to free all temp data if we were not on this planet once the BuildFinally is done diff --git a/NebulaModel/Packets/Players/NewDroneOrderPacket.cs b/NebulaModel/Packets/Players/NewDroneOrderPacket.cs index da0015474..820cfdf57 100644 --- a/NebulaModel/Packets/Players/NewDroneOrderPacket.cs +++ b/NebulaModel/Packets/Players/NewDroneOrderPacket.cs @@ -1,4 +1,7 @@ -namespace NebulaModel.Packets.Players +using NebulaModel.DataStructures; +using UnityEngine; + +namespace NebulaModel.Packets.Players { public class NewDroneOrderPacket { @@ -8,9 +11,10 @@ public class NewDroneOrderPacket public ushort PlayerId { get; set; } public int Stage { get; set; } public int Priority { get; set; } + public Float3 EntityPos { get; set; } public NewDroneOrderPacket() { } - public NewDroneOrderPacket(int planetId, int droneId, int entityId, ushort playerId, int stage, int priority) + public NewDroneOrderPacket(int planetId, int droneId, int entityId, ushort playerId, int stage, int priority, Vector3 entityPos) { PlanetId = planetId; DroneId = droneId; @@ -18,6 +22,7 @@ public NewDroneOrderPacket(int planetId, int droneId, int entityId, ushort playe PlayerId = playerId; Stage = stage; Priority = priority; + EntityPos = entityPos.ToFloat3(); } } } diff --git a/NebulaPatcher/Patches/Dynamic/PlanetFactory_Patch.cs b/NebulaPatcher/Patches/Dynamic/PlanetFactory_Patch.cs index 4dde95bba..754763371 100644 --- a/NebulaPatcher/Patches/Dynamic/PlanetFactory_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/PlanetFactory_Patch.cs @@ -6,6 +6,7 @@ using NebulaWorld.Factory; using UnityEngine; using NebulaWorld.Planet; +using NebulaWorld.Player; namespace NebulaPatcher.Patches.Dynamic { @@ -55,6 +56,11 @@ public static bool BuildFinally_Prefix(PlanetFactory __instance, Player player, LocalPlayer.SendPacket(new BuildEntityRequest(__instance.planetId, prebuildId)); } + if (!LocalPlayer.IsMasterClient && !FactoryManager.EventFromServer) + { + DroneManager.AddBuildRequestSent(-prebuildId); + } + return LocalPlayer.IsMasterClient || FactoryManager.EventFromServer; } diff --git a/NebulaPatcher/Patches/Transpilers/MechaDroneLogic_Patch.cs b/NebulaPatcher/Patches/Transpilers/MechaDroneLogic_Patch.cs index 4eb3cca68..6197b5c57 100644 --- a/NebulaPatcher/Patches/Transpilers/MechaDroneLogic_Patch.cs +++ b/NebulaPatcher/Patches/Transpilers/MechaDroneLogic_Patch.cs @@ -8,14 +8,14 @@ namespace NebulaPatcher.Patches.Transpiler [HarmonyPatch(typeof(MechaDroneLogic))] class MechaDroneLogic_Patch { - /* - * Call DroneManager.BroadcastDroneOrder(int droneId, int entityId, int stage) when drone gets new order - */ [HarmonyTranspiler] [HarmonyPatch("UpdateTargets")] static IEnumerable UpdateTargets_Transpiler(IEnumerable instructions) { var codes = new List(instructions); + /* + * Call DroneManager.BroadcastDroneOrder(int droneId, int entityId, int stage) when drone gets new order + */ for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Pop && @@ -32,6 +32,32 @@ static IEnumerable UpdateTargets_Transpiler(IEnumerable this.sqrMinBuildAlt && sqrMagnitude <= num2 && !this.serving.Contains(num4)) + * + * To: + if (a.sqrMagnitude > this.sqrMinBuildAlt && sqrMagnitude <= num2 && !this.serving.Contains(num4) && !DroneManager.IsPendingBuildRequest(num4)) + */ + for (int i = 0; i < codes.Count; i++) + { + if (codes[i].opcode == OpCodes.Brtrue && + codes[i - 1].opcode == OpCodes.Callvirt && + codes[i + 1].opcode == OpCodes.Ldloc_S && + codes[i - 2].opcode == OpCodes.Ldloc_S && + codes[i + 2].opcode == OpCodes.Stloc_2) + { + codes.InsertRange(i + 1, new CodeInstruction[] { + new CodeInstruction(OpCodes.Ldloc_S, 6), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(DroneManager), nameof(DroneManager.IsPendingBuildRequest), new System.Type[] { typeof(int) })), + new CodeInstruction(OpCodes.Brtrue_S, codes[i].operand), + }); + break; + } + } + return codes; } diff --git a/NebulaWorld/Player/DroneManager.cs b/NebulaWorld/Player/DroneManager.cs index c3d1a8489..5a674c36f 100644 --- a/NebulaWorld/Player/DroneManager.cs +++ b/NebulaWorld/Player/DroneManager.cs @@ -9,16 +9,26 @@ public static class DroneManager public static int[] DronePriorities = new int[255]; public static Random rnd = new Random(); public static Dictionary> PlayerDroneBuildingPlans = new Dictionary>(); + public static List PendingBuildRequests = new List(); public static void BroadcastDroneOrder(int droneId, int entityId, int stage) { + if (!SimulatedWorld.Initialized) + { + return; + } + int priority = 0; if (stage == 1 || stage == 2) { priority = rnd.Next(); DronePriorities[droneId] = priority; } - LocalPlayer.SendPacketToLocalPlanet(new NewDroneOrderPacket(GameMain.mainPlayer.planetId, droneId, entityId, LocalPlayer.PlayerId, stage, priority)); + else + { + GameMain.mainPlayer.mecha.droneLogic.serving.Remove(entityId); + } + LocalPlayer.SendPacketToLocalPlanet(new NewDroneOrderPacket(GameMain.mainPlayer.planetId, droneId, entityId, LocalPlayer.PlayerId, stage, priority, GameMain.localPlanet.factory.prebuildPool[-entityId].pos)); } public static void AddPlayerDronePlan(ushort playerId, int entityId) @@ -46,5 +56,20 @@ public static int[] GetPlayerDronePlans(ushort playerId) } return null; } + + public static void AddBuildRequestSent(int entityId) + { + PendingBuildRequests.Add(entityId); + } + + public static bool IsPendingBuildRequest(int entityId) + { + return PendingBuildRequests.Contains(entityId); + } + + public static bool RemoveBuildRequest(int entityId) + { + return PendingBuildRequests.Remove(entityId); + } } } diff --git a/NebulaWorld/SimulatedWorld.cs b/NebulaWorld/SimulatedWorld.cs index 87fb093ad..9e6e23b14 100644 --- a/NebulaWorld/SimulatedWorld.cs +++ b/NebulaWorld/SimulatedWorld.cs @@ -176,6 +176,19 @@ public static void UpdateRemotePlayerDrone(NewDroneOrderPacket packet) if (drone.stage == 1 || drone.stage == 2) { + //Check if target entity exists as Prebuild + if (GameMain.data.localPlanet.factory.prebuildPool.Length <= -packet.EntityId || GameMain.data.localPlanet.factory.prebuildPool[-packet.EntityId].id == 0) + { + return; + } + + //Check target prebuild if it is same prebuild that I have. Sometimes it is same ID, but different prebuild + ref PrebuildData prebuildData = ref GameMain.data.localPlanet.factory.prebuildPool[-packet.EntityId]; + if (prebuildData.pos.x != packet.EntityPos.x || prebuildData.pos.y != packet.EntityPos.y || prebuildData.pos.z != packet.EntityPos.z) + { + return; + } + //Check if my drone is already going there if (!myMecha.droneLogic.serving.Contains(packet.EntityId)) { @@ -448,7 +461,13 @@ public static void OnDronesGameTick(long time, float dt) //Update only moving drones of players on the same planet if (drones[i].stage != 0 && GameMain.mainPlayer.planetId == remoteModel.Value.Movement.localPlanetId) { - drones[i].Update(prebuildPool, remotePosition, dt, ref tmp, ref tmp2, 0); + if (drones[i].Update(prebuildPool, remotePosition, dt, ref tmp, ref tmp2, 0) != 0) + { + //Reset drone and release lock + drones[i].stage = 3; + GameMain.mainPlayer.mecha.droneLogic.serving.Remove(drones[i].targetObject); + drones[i].targetObject = 0; + } } } remoteMecha.droneRenderer.Update();