public static void UpdateRemotePlayerDrone(NewDroneOrderPacket packet) { using (GetRemotePlayersModels(out var remotePlayersModels)) { if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel player)) { //Setup drone of remote player based on the drone data ref MechaDrone drone = ref player.PlayerInstance.mecha.drones[packet.DroneId]; MechaDroneLogic droneLogic = player.PlayerInstance.mecha.droneLogic; drone.stage = packet.Stage; drone.targetObject = packet.Stage < 3 ? packet.EntityId : 0; drone.movement = droneLogic.player.mecha.droneMovement; if (packet.Stage == 1) { drone.position = player.Movement.GetLastPosition().LocalPlanetPosition.ToVector3(); } drone.target = (Vector3)MethodInvoker.GetHandler(AccessTools.Method(typeof(MechaDroneLogic), "_obj_hpos", new System.Type[] { typeof(int) })).Invoke(GameMain.mainPlayer.mecha.droneLogic, packet.EntityId); drone.initialVector = drone.position + drone.position.normalized * 4.5f + ((drone.target - drone.position).normalized + UnityEngine.Random.insideUnitSphere) * 1.5f; drone.forward = drone.initialVector; drone.progress = 0f; player.MechaInstance.droneCount = GameMain.mainPlayer.mecha.droneCount; player.MechaInstance.droneSpeed = GameMain.mainPlayer.mecha.droneSpeed; if (packet.Stage == 3) { GameMain.mainPlayer.mecha.droneLogic.serving.Remove(packet.EntityId); } } }
public static void UpdateDronesPrefix(MechaDroneLogic __instance) { foreach (var prebuild in __instance.factory.prebuildPool) { __instance.factory.BuildFinally(__instance.player, prebuild.id); } }
public static void UpdateRemotePlayerDrone(NewDroneOrderPacket packet) { using (GetRemotePlayersModels(out var remotePlayersModels)) { if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel player)) { //Setup drone of remote player based on the drone data ref MechaDrone drone = ref player.PlayerInstance.mecha.drones[packet.DroneId]; MechaDroneLogic droneLogic = player.PlayerInstance.mecha.droneLogic; drone.stage = packet.Stage; drone.targetObject = packet.Stage < 3 ? packet.EntityId : 0; drone.movement = droneLogic.player.mecha.droneMovement; if (packet.Stage == 1) { drone.position = player.Movement.GetLastPosition().LocalPlanetPosition.ToVector3(); } drone.target = (Vector3)MethodInvoker.GetHandler(AccessTools.Method(typeof(MechaDroneLogic), "_obj_hpos", new System.Type[] { typeof(int) })).Invoke(GameMain.mainPlayer.mecha.droneLogic, packet.EntityId); drone.initialVector = drone.position + drone.position.normalized * 4.5f + ((drone.target - drone.position).normalized + UnityEngine.Random.insideUnitSphere) * 1.5f; drone.forward = drone.initialVector; drone.progress = 0f; player.MechaInstance.droneCount = GameMain.mainPlayer.mecha.droneCount; player.MechaInstance.droneSpeed = GameMain.mainPlayer.mecha.droneSpeed; Mecha myMecha = GameMain.mainPlayer.mecha; if (packet.Stage == 3) { myMecha.droneLogic.serving.Remove(packet.EntityId); } 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)) { myMecha.droneLogic.serving.Add(packet.EntityId); } else { //resolve conflict (two drones are going to the same building) //find my drone that is going there int priority = 0; int droneId = 0; for (int i = 0; i < myMecha.droneCount; i++) { if (myMecha.drones[i].stage > 0 && myMecha.drones[i].targetObject == drone.targetObject) { priority = DroneManager.DronePriorities[i]; droneId = i; break; } } ref MechaDrone myDrone = ref myMecha.drones[droneId]; //for size comparison sqrMagnitude is fine, since sqrMagnitude, magnitude and the actual distance along the curve are all strictly monotonically increasing float diff = (myDrone.position - myDrone.target).sqrMagnitude - (drone.position - drone.target).sqrMagnitude; if (diff > 0 || (diff == 0 && packet.Priority > priority)) { //my drone is further away (myMagnitude > otherMagnitude = difference positive) and has to return myDrone.stage = 3; myDrone.targetObject = 0; } else { //their drone is further away (otherMagnitude > myMagnitude = difference negative) and has to return drone.stage = 3; drone.targetObject = 0; } } }
public static void UpdateRemotePlayerDrone(NewDroneOrderPacket packet) { using (GetRemotePlayersModels(out var remotePlayersModels)) { if (remotePlayersModels.TryGetValue(packet.PlayerId, out RemotePlayerModel player)) { //Setup drone of remote player based on the drone data ref MechaDrone drone = ref player.PlayerInstance.mecha.drones[packet.DroneId]; MechaDroneLogic droneLogic = player.PlayerInstance.mecha.droneLogic; drone.stage = packet.Stage; drone.targetObject = packet.Stage < 3 ? packet.EntityId : 0; drone.movement = droneLogic.player.mecha.droneMovement; if (packet.Stage == 1) { drone.position = player.Movement.GetLastPosition().LocalPlanetPosition.ToVector3(); } drone.target = (Vector3)MethodInvoker.GetHandler(AccessTools.Method(typeof(MechaDroneLogic), "_obj_hpos", new System.Type[] { typeof(int) })).Invoke(GameMain.mainPlayer.mecha.droneLogic, packet.EntityId); drone.initialVector = drone.position + drone.position.normalized * 4.5f + ((drone.target - drone.position).normalized + UnityEngine.Random.insideUnitSphere) * 1.5f; drone.forward = drone.initialVector; drone.progress = 0f; player.MechaInstance.droneCount = GameMain.mainPlayer.mecha.droneCount; player.MechaInstance.droneSpeed = GameMain.mainPlayer.mecha.droneSpeed; Mecha myMecha = GameMain.mainPlayer.mecha; if (packet.Stage == 3) { myMecha.droneLogic.serving.Remove(packet.EntityId); } if (drone.stage == 1 || drone.stage == 2) { //Check if my drone is already going there if (!myMecha.droneLogic.serving.Contains(packet.EntityId)) { myMecha.droneLogic.serving.Add(packet.EntityId); } else { //resolve conflict (two drones are going to the same building) //find my drone that is going there int priority = 0; int droneId = 0; for (int i = 0; i < myMecha.droneCount; i++) { if (myMecha.drones[i].stage > 0 && myMecha.drones[i].targetObject == drone.targetObject) { priority = DroneManager.DronePriorities[i]; droneId = i; break; } } //compare, who's drone has higher priority if (packet.Priority > priority) { //their drone won, my drone has to return ref MechaDrone myDrone = ref myMecha.drones[droneId]; myDrone.stage = 3; myDrone.targetObject = 0; } else { //my drone won, their has to return drone.stage = 3; drone.targetObject = 0; } } }
public static void MechaDroneLogic_UpdateTargets_Prefix(MechaDroneLogic __instance, Player ___player) { if (___player.factory != null) { if (GameMain.data.hidePlayerModel) { if (configEnableDebug) { Logger.LogInfo("Skipping because player model is hidden. This is needed for compatability with the Render Distance mod."); } UpdateTipText("(Player hidden.)"); return; } if (!configEnableMod.Value) { if (configEnableDebug) { Logger.LogInfo("Skipping because mod is disabled."); } return; } if (___player.movementState == EMovementState.Sail) { if (configEnableDebug) { Logger.LogInfo("Skipping because movement state is Sail."); } UpdateTipText("(Waiting while Sailing.)"); RecallClearingDrones(); return; } if (___player.movementState == EMovementState.Drift && !configEnableClearingWhileDrifting) { if (configEnableDebug) { Logger.LogInfo("Skipping while drifting."); } UpdateTipText("(Waiting while Drifting.)"); return; } if (___player.movementState == EMovementState.Fly && !configEnableClearingWhileFlying) { if (configEnableRecallWhileFlying) { if (configEnableDebug) { Logger.LogInfo("Recalling drones."); } RecallClearingDrones(); } else if (configEnableDebug) { Logger.LogInfo("Skipping while flying."); } UpdateTipText("(Waiting while Flying.)"); return; } if (___player.mecha.coreEnergy < ___player.mecha.droneEjectEnergy) { if (configEnableDebug) { Logger.LogInfo("Skipping because of insufficient mecha energy to eject a drone."); } UpdateTipText("(Waiting for ejection energy.)"); return; } if ((___player.planetData.type == EPlanetType.None && !configEnableClearingPlanetGeneric) || (___player.planetData.type == EPlanetType.Vocano && !configEnableClearingPlanetVocano) || (___player.planetData.type == EPlanetType.Ocean && !configEnableClearingPlanetOcean) || (___player.planetData.type == EPlanetType.Desert && !configEnableClearingPlanetDesert) || (___player.planetData.type == EPlanetType.Ice && !configEnableClearingPlanetIce)) { if (configEnableDebug) { Logger.LogInfo("Skipping planet type " + ___player.planetData.type.ToString()); } UpdateTipText("(Waiting on this planet type.)"); return; } int totalDroneTaskingCount = getTotalDroneTaskingCount(); if (totalDroneTaskingCount >= Math.Min(configMaxClearingDroneCount, ___player.mecha.droneCount)) { if (configEnableDebug) { var sbc = new StringBuilder(); sbc.AppendFormat("Skipping due to number of drone assignments: totalDroneTaskingCount={0}, configMaxClearingDroneCount={1}, player.mecha.droneCount={2}, player.mecha.idleDroneCount={3}", totalDroneTaskingCount, configMaxClearingDroneCount, ___player.mecha.droneCount, ___player.mecha.idleDroneCount); Logger.LogInfo(sbc.ToString()); } UpdateTipText("(Available drones assigned.)"); return; } if (___player.mecha.coreEnergy / ___player.mecha.coreEnergyCap < configReservedPower) { if (configEnableDebug) { Logger.LogInfo("Skipping due to low power."); } UpdateTipText("(Waiting for energy.)"); return; } if (configCollectResourcesFlag) // ... check configReservedInventorySpace { uint numEmptyInventorySlots = 0; for (int gridIdx = 0; gridIdx < ___player.package.size; ++gridIdx) { if (___player.package.grids[gridIdx].count == 0) { numEmptyInventorySlots++; } } if (numEmptyInventorySlots < configReservedInventorySpace) { if (configEnableDebug) { Logger.LogInfo("Too few inventory slots"); } UpdateTipText("(Waiting for inventory space.)"); return; } } float closestVegeDistance = ___player.mecha.buildArea * configLimitClearingDistance * 2; int closestVegeId = -1; foreach (VegeData vegeData in ___player.factory.vegePool) { VegeProto vegeProto = LDB.veges.Select((int)vegeData.protoId); // vegeProto.Type == EVegeType.Detail covers grass and small minable rocks. So the check includes vegeProto.MiningItem.Length instead. if (vegeProto != null && vegeProto.MiningItem.Length > 0) { if ((vegeProto.Type == EVegeType.Tree && !configEnableClearingItemTree) || (vegeProto.Type == EVegeType.Stone && !configEnableClearingItemStone) || (vegeProto.Type == EVegeType.Detail && !configEnableClearingItemDetail) || (vegeProto.Type == EVegeType.Ice && !configEnableClearingItemIce)) { continue; } float distanceToVege = Vector3.Distance(___player.position, vegeData.pos); if (distanceToVege < closestVegeDistance) { bool vegeBeingProcessedFlag = false; foreach (PrebuildData prebuild in ___player.factory.prebuildPool) { if (isDroneClearingPrebuild(prebuild) && prebuild.upEntity == vegeData.id) { vegeBeingProcessedFlag = true; break; } } if (!vegeBeingProcessedFlag) { closestVegeDistance = distanceToVege; closestVegeId = vegeData.id; } } } } if (closestVegeDistance <= ___player.mecha.buildArea * configLimitClearingDistance) { VegeData vegeData = ___player.factory.vegePool[closestVegeId]; VegeProto vegeProto = LDB.veges.Select((int)vegeData.protoId); //var sb = new StringBuilder(); //sb.AppendFormat("Initiating mining of {0} to get {1} at power level {2}", vegeProto.Type.ToString(), LDB.items.Select(vegeProto.MiningItem[0]).name, ___player.mecha.coreEnergy / ___player.mecha.coreEnergyCap); //Logger.LogInfo(sb.ToString()); PrebuildData prebuild = default; prebuild.protoId = -1; prebuild.modelId = 0; // Saves always open as 0 prebuild.recipeId = -1; prebuild.refCount = 0; prebuild.upEntity = vegeData.id; prebuild.pos = prebuild.pos2 = vegeData.pos; prebuild.rot = vegeData.rot; // This operation will cause a drone to be assigned by MechaDroneLogic.UpdateTargets. int prebuildId = ___player.factory.AddPrebuildData(prebuild); UpdateTipText("(Assigning drones.)"); } else { if (configEnableDebug) { Logger.LogInfo("No enabled items within configured distance."); } UpdateTipText("(No more items in range.)"); } } }