diff --git a/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsRequest.cs b/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsRequest.cs index 74ff5fa1f..8c613d91d 100644 --- a/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsRequest.cs +++ b/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsRequest.cs @@ -18,7 +18,7 @@ public LCPFilterResultsRequest(in ControlPanelFilter controlPanelFilter) } else { - ItemsFilter = new int[0]; + ItemsFilter = Array.Empty(); } StateFilter = controlPanelFilter.stateFilter; SearchFilter = controlPanelFilter.searchFilter; @@ -26,7 +26,7 @@ public LCPFilterResultsRequest(in ControlPanelFilter controlPanelFilter) LocalPlanetAstroId = GameMain.data.localPlanet?.astroId ?? 0; LocalStarAstroId = GameMain.data.localStar?.astroId ?? 0; - PlayerUposition = new Float3(GameMain.mainPlayer.uPosition); + PlayerUposition = new Double3(GameMain.mainPlayer.uPosition.x, GameMain.mainPlayer.uPosition.y, GameMain.mainPlayer.uPosition.z); } public int TypeFilter { get; set; } @@ -37,5 +37,5 @@ public LCPFilterResultsRequest(in ControlPanelFilter controlPanelFilter) public short SortMethod { get; set; } public int LocalPlanetAstroId { get; set; } public int LocalStarAstroId { get; set; } - public Float3 PlayerUposition { get; set; } + public Double3 PlayerUposition { get; set; } } diff --git a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsRequestProcessor.cs b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsRequestProcessor.cs index 95ca5d169..8c3a75f66 100644 --- a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsRequestProcessor.cs +++ b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsRequestProcessor.cs @@ -38,7 +38,7 @@ protected override void ProcessPacket(LCPFilterResultsRequest packet, NebulaConn var factoryCount = GameMain.data.factoryCount; var localPlanetAstroId = packet.LocalPlanetAstroId; var localStarAstroId = packet.LocalStarAstroId; - ref var ptr = ref GameMain.data.mainPlayer.uPosition; + var playerUPosition = new VectorLF3(packet.PlayerUposition.x, packet.PlayerUposition.y, packet.PlayerUposition.z); var factories = GameMain.data.factories; var galaxyAstros = GameMain.data.spaceSector.galaxyAstros; @@ -47,7 +47,7 @@ protected override void ProcessPacket(LCPFilterResultsRequest packet, NebulaConn var astroId = factories[i].planet.astroId; if (filter.sortMethod == ControlPanelFilter.ESortMethod.AstroDistance) { - var sqrMagnitude = (galaxyAstros[astroId].uPos - ptr).sqrMagnitude; + var sqrMagnitude = (galaxyAstros[astroId].uPos - playerUPosition).sqrMagnitude; var index = sortedAstros.Count - 1; while (index >= 0 && sqrMagnitude < sortedAstros[index].sqrDistToPlayer) { diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelObjectEntry_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelObjectEntry_Patch.cs index 8dd621217..da99f676c 100644 --- a/NebulaPatcher/Patches/Dynamic/UIControlPanelObjectEntry_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelObjectEntry_Patch.cs @@ -24,5 +24,16 @@ static IEnumerable Transpiler(IEnumerable inst return instructions; } } -} + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelObjectEntry.OnSelectButtonClick))] + public static void OnSelectButtonClick_Postfix(UIControlPanelObjectEntry __instance) + { + if (!__instance.isTargetDataValid) + { + // The main reason why target data is invalid is due to remote planet is not loaded for client + // So make a popup here to info the user about this behavior + UIRealtimeTip.Popup("Can't view remote planet for MP client!".Translate()); + } + } +} diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelStationInspector_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelStationInspector_Patch.cs index 14ac5256d..8e095bcb9 100644 --- a/NebulaPatcher/Patches/Dynamic/UIControlPanelStationInspector_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelStationInspector_Patch.cs @@ -1,7 +1,10 @@ #region +using System; using HarmonyLib; +using NebulaModel.Packets.Logistics; using NebulaWorld; +using UnityEngine; #endregion @@ -10,13 +13,476 @@ namespace NebulaPatcher.Patches.Dynamic; [HarmonyPatch(typeof(UIControlPanelStationInspector))] internal class UIControlPanelStationInspector_Patch { - [HarmonyPostfix, HarmonyPriority(Priority.Last)] + private static long lastUpdateGametick; + private static StationUI SliderBarPacket = new(); + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnMaxChargePowerSliderValueChange))] + public static bool OnMaxChargePowerSliderValueChange_Prefix(UIControlPanelStationInspector __instance, float value) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + SliderBarPacket.SettingIndex = StationUI.EUISettings.MaxChargePower; + SliderBarPacket.SettingValue = value; + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return Multiplayer.Session.LocalPlayer.IsHost; + } + StringBuilderUtility.WriteKMG(__instance.powerServedSB, 8, (long)(3000000.0 * value + 0.5)); + __instance.maxChargePowerValue.text = __instance.powerServedSB.ToString(); + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnMaxTripDroneSliderValueChange))] + public static bool OnMaxTripDroneSliderValueChange_Prefix(UIControlPanelStationInspector __instance, float value) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + SliderBarPacket.SettingIndex = StationUI.EUISettings.MaxTripDrones; + SliderBarPacket.SettingValue = value; + if (Multiplayer.Session.LocalPlayer.IsClient) + { + __instance.maxTripDroneValue.text = value.ToString("0 °"); + } + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnMaxTripVesselSliderValueChange))] + public static bool OnMaxTripVesselSliderValueChange_Prefix(UIControlPanelStationInspector __instance, float value) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + SliderBarPacket.SettingIndex = StationUI.EUISettings.MaxTripVessel; + SliderBarPacket.SettingValue = value; + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return Multiplayer.Session.LocalPlayer.IsHost; + } + var num = value switch + { + > 40.5f => 10000.0f, + > 20.5f => value * 2f - 20f, + _ => value + }; + __instance.maxTripVesselValue.text = num < 9999.0f ? num.ToString("0 ly") : "∞"; + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnMinDeliverDroneValueChange))] + public static bool OnMinDeliverDroneValueChange_Prefix(UIControlPanelStationInspector __instance, float value) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + SliderBarPacket.SettingIndex = StationUI.EUISettings.MinDeliverDrone; + SliderBarPacket.SettingValue = value; + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return Multiplayer.Session.LocalPlayer.IsHost; + } + var num = (int)(value * 10f + 0.5f); + if (num < 1) + { + num = 1; + } + __instance.minDeliverDroneValue.text = num.ToString("0") + " %"; + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnMinDeliverVesselValueChange))] + public static bool OnMinDeliverVesselValueChange_Prefix(UIControlPanelStationInspector __instance, float value) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + SliderBarPacket.SettingIndex = StationUI.EUISettings.MinDeliverVessel; + SliderBarPacket.SettingValue = value; + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return Multiplayer.Session.LocalPlayer.IsHost; + } + var num = (int)(value * 10f + 0.5f); + num = num < 1 ? 1 : num; + __instance.minDeliverVesselValue.text = num.ToString("0") + " %"; + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnMaxMiningSpeedChange))] + public static bool OnMaxMiningSpeedChanged_Prefix(UIControlPanelStationInspector __instance, float value) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + SliderBarPacket.SettingIndex = StationUI.EUISettings.MaxMiningSpeed; + SliderBarPacket.SettingValue = value; + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return Multiplayer.Session.LocalPlayer.IsHost; + } + var num = 10000 + (int)(value + 0.5f) * 1000; + __instance.maxMiningSpeedValue.text = (num / 100).ToString("0") + " %"; + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnWarperDistanceValueChange))] + public static bool OnWarperDistanceValueChange_Prefix(UIControlPanelStationInspector __instance, float value) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + // make minimum value set at 0.5 ly + if (value < 2f) + { + value = 2f; + __instance.event_lock = true; + __instance.warperDistanceSlider.value = 2f; + __instance.event_lock = false; + } + SliderBarPacket.SettingIndex = StationUI.EUISettings.WarpDistance; + SliderBarPacket.SettingValue = value; + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return Multiplayer.Session.LocalPlayer.IsHost; + } + float num; + if (value < 1.5) + { + num = 0.2f; + } + else if (value < 7.5) + { + num = value * 0.5f - 0.5f; + } + else if (value < 16.5) + { + num = value - 4f; + } + else if (value < 20.5) + { + num = value * 2f - 20f; + } + else + { + num = 60.0f; + } + __instance.warperDistanceValue.text = num < 10.0 ? num.ToString("0.0 AU") : num.ToString("0 AU"); + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnMinPilerValueChange))] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnTechPilerClick))] + public static void OnPilerCountChange(UIControlPanelStationInspector __instance) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + var packet = new StationUI(__instance.factory.planet.id, stationComponent.id, stationComponent.gid, + StationUI.EUISettings.PilerCount, stationComponent.pilerCount); + Multiplayer.Session.Network.SendPacket(packet); + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnWarperNecessaryClick))] + public static bool OnWarperNecessaryClick_Prefix(UIControlPanelStationInspector __instance) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + var packet = new StationUI(__instance.factory.planet.id, + __instance.factory.transport.stationPool[__instance.stationId].id, + __instance.factory.transport.stationPool[__instance.stationId].gid, StationUI.EUISettings.WarperNeeded, 0f); + Multiplayer.Session.Network.SendPacket(packet); + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnIncludeOrbitCollectorClick))] + public static bool OnIncludeOrbitCollectorClick_Prefix(UIControlPanelStationInspector __instance) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return true; + } + var packet = new StationUI(__instance.factory.planet.id, + __instance.factory.transport.stationPool[__instance.stationId].id, + __instance.factory.transport.stationPool[__instance.stationId].gid, StationUI.EUISettings.IncludeCollectors, 0f); + Multiplayer.Session.Network.SendPacket(packet); + return Multiplayer.Session.LocalPlayer.IsHost; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnDroneIconClick))] + [HarmonyPriority(Priority.First)] + public static void OnDroneIconClick_Prefix(UIControlPanelStationInspector __instance, ref int __state) + { + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + __state = stationComponent.idleDroneCount; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnDroneIconClick))] + [HarmonyPriority(Priority.Last)] + public static void OnDroneIconClick_Postfix(UIControlPanelStationInspector __instance, int __state) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + if (__state == stationComponent.idleDroneCount) + { + return; + } + var droneCount = stationComponent.idleDroneCount + stationComponent.workDroneCount; + var packet = new StationUI(__instance.factory.planet.id, stationComponent.id, stationComponent.gid, + StationUI.EUISettings.SetDroneCount, droneCount); + Multiplayer.Session.Network.SendPacket(packet); + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return; + } + // Revert drone count until host verify + stationComponent.idleDroneCount = __state; + __instance.droneIconButton.button.interactable = false; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnDroneAutoReplenishButtonClick))] + public static void OnDroneAutoReplenishButtonClick_Postfix(UIControlPanelStationInspector __instance) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + var packet = new StationUI(__instance.factory.planet.id, stationComponent.id, stationComponent.gid, + StationUI.EUISettings.DroneAutoReplenish, stationComponent.droneAutoReplenish ? 1f : 0f); + Multiplayer.Session.Network.SendPacket(packet); + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnShipIconClick))] + [HarmonyPriority(Priority.First)] + public static void OnShipIconClick_Prefix(UIControlPanelStationInspector __instance, ref int __state) + { + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + __state = stationComponent.idleShipCount; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnShipIconClick))] + [HarmonyPriority(Priority.Last)] + public static void OnShipIconClick_Postfix(UIControlPanelStationInspector __instance, int __state) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + if (__state == stationComponent.idleShipCount) + { + return; + } + var ShipCount = stationComponent.idleShipCount + stationComponent.workShipCount; + var packet = new StationUI(__instance.factory.planet.id, stationComponent.id, stationComponent.gid, + StationUI.EUISettings.SetShipCount, ShipCount); + Multiplayer.Session.Network.SendPacket(packet); + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return; + } + // Revert ship count until host verify + stationComponent.idleShipCount = __state; + __instance.shipIconButton.button.interactable = false; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnShipAutoReplenishButtonClick))] + public static void OnShipAutoReplenishButtonClick_Postfix(UIControlPanelStationInspector __instance) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + var packet = new StationUI(__instance.factory.planet.id, stationComponent.id, stationComponent.gid, + StationUI.EUISettings.ShipAutoReplenish, stationComponent.shipAutoReplenish ? 1f : 0f); + Multiplayer.Session.Network.SendPacket(packet); + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnWarperIconClick))] + [HarmonyPriority(Priority.First)] + public static void OnWarperIconClick_Prefix(UIControlPanelStationInspector __instance, ref int __state) + { + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + __state = stationComponent.warperCount; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnWarperIconClick))] + [HarmonyPriority(Priority.Last)] + public static void OnWarperIconClick_Postfix(UIControlPanelStationInspector __instance, int __state) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + if (__state == stationComponent.warperCount) + { + return; + } + var packet = new StationUI(__instance.factory.planet.id, stationComponent.id, stationComponent.gid, + StationUI.EUISettings.SetWarperCount, stationComponent.warperCount); + Multiplayer.Session.Network.SendPacket(packet); + if (!Multiplayer.Session.LocalPlayer.IsClient) + { + return; + } + // Revert warper count until host verify + stationComponent.warperCount = __state; + __instance.warperIconButton.button.interactable = false; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnGroupButtonClick))] + public static void OnGroupButtonClick_Postfix(UIControlPanelStationInspector __instance) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + + if (__instance.stationId == 0 || __instance.factory == null) + { + return; + } + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + var packet = new StationUI(__instance.factory.planet.id, stationComponent.id, stationComponent.gid, + StationUI.EUISettings.RemoteGroupMask, BitConverter.Int64BitsToDouble(stationComponent.remoteGroupMask)); + Multiplayer.Session.Network.SendPacket(packet); + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnBehaviorBomboBoxItemIndexChange))] + public static void OnBehaviorBomboBoxItemIndexChange_Postfix(UIControlPanelStationInspector __instance) + { + if (__instance.event_lock || !Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + + if (__instance.stationId == 0 || __instance.factory == null) + { + return; + } + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + var packet = new StationUI(__instance.factory.planet.id, stationComponent.id, stationComponent.gid, + StationUI.EUISettings.RoutePriority, (int)stationComponent.routePriority); + Multiplayer.Session.Network.SendPacket(packet); + } + + [HarmonyPostfix] [HarmonyPatch(nameof(UIControlPanelStationInspector._OnOpen))] - public static void OnOpen_Postfix(UIControlPanelStationInspector __instance) + public static void _OnOpen_Postfix(UIControlPanelStationInspector __instance) + { + if (!Multiplayer.IsActive || __instance.transport == null) + { + return; + } + + lastUpdateGametick = 0; + var stationComponent = __instance.transport.stationPool[__instance.stationId]; + SliderBarPacket = new StationUI(__instance.factory.planet.id, stationComponent.id, + stationComponent.gid, StationUI.EUISettings.None, 0); + Multiplayer.Session.StationsUI.StorageMaxChangeId = -1; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationInspector._OnUpdate))] + public static void _OnUpdate_Prefix(UIControlPanelStationInspector __instance) + { + if (!Multiplayer.IsActive) + { + return; + } + + // When releasing left mouse button + if (Input.GetMouseButtonUp(0)) + { + if (SliderBarPacket.SettingIndex != StationUI.EUISettings.None) + { + // Send SliderBarPacket when left mouse button is released + Multiplayer.Session.Network.SendPacket(SliderBarPacket); + SliderBarPacket.SettingIndex = StationUI.EUISettings.None; + } + if (Multiplayer.Session.StationsUI.StorageMaxChangeId >= 0) + { + // Do the job in UIStationStorage.OnMaxSliderValueChange() + var index = Multiplayer.Session.StationsUI.StorageMaxChangeId; + var val = __instance.storageUIs[index].maxSlider.value; + var stationStore = __instance.transport.stationPool[__instance.stationId].storage[index]; + __instance.transport.SetStationStorage(__instance.stationId, index, stationStore.itemId, + (int)(val * 100f + 0.5f), stationStore.localLogic, stationStore.remoteLogic, GameMain.mainPlayer); + + // In client side, preserve displaying slider value until host response + Multiplayer.Session.StationsUI.StorageMaxChangeId = Multiplayer.Session.LocalPlayer.IsHost ? -1 : -2; + } + } + + // Request for remoteOrder update every 60tick + if (!Multiplayer.Session.LocalPlayer.IsClient || GameMain.gameTick - lastUpdateGametick <= 60) + { + return; + } + var gid = __instance.transport?.stationPool?[__instance.stationId].gid ?? 0; + if (gid > 0) + { + Multiplayer.Session.Network.SendPacket(new RemoteOrderUpdate(gid, Array.Empty())); + } + lastUpdateGametick = GameMain.gameTick; + + return; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationInspector.OnStationIdChange))] + public static void OnStationIdChange_Postfix(UIControlPanelStationInspector __instance) { - if (!Multiplayer.IsActive) return; + if (!Multiplayer.IsActive || Multiplayer.Session.LocalPlayer.IsHost) + { + return; + } - // Temporarily disable the station window, as we need to deal with remote station and sync in the future - __instance._Close(); + __instance.warperIconButton.button.interactable = true; + __instance.shipIconButton.button.interactable = true; + __instance.droneIconButton.button.interactable = true; } } diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelStationStorage_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelStationStorage_Patch.cs new file mode 100644 index 000000000..971b10f4f --- /dev/null +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelStationStorage_Patch.cs @@ -0,0 +1,136 @@ +#region + +using System; +using HarmonyLib; +using NebulaModel.Packets.Logistics; +using NebulaWorld; +// ReSharper disable RedundantAssignment + +#endregion + +namespace NebulaPatcher.Patches.Dynamic; + +[HarmonyPatch(typeof(UIControlPanelStationStorage))] +internal class UIControlPanelStationStorage_Patch +{ + private static bool eventLock; + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationStorage.OnMaxSliderValueChange))] + public static bool OnMaxSliderValueChangePrefix(UIControlPanelStationStorage __instance, float val) + { + if (!Multiplayer.IsActive || eventLock) + { + return !Multiplayer.IsActive; + } + if (Math.Abs(val - __instance.station.storage[__instance.index].max / 100f) > 0.000000001) + { + // If the slider value doesn't match with storage.max, mark it + Multiplayer.Session.StationsUI.StorageMaxChangeId = __instance.index; + } + return !Multiplayer.IsActive; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationStorage._OnUpdate))] + public static void _OnUpdate_Prefix(UIControlPanelStationStorage __instance, ref float __state) + { + // Set up eventLock so value changes in maxSlider.value don't trigger changed check + eventLock = true; + __state = __instance.maxSlider.value; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationStorage._OnUpdate))] + public static void _OnUpdate_Postfix(UIControlPanelStationStorage __instance, float __state) + { + // Restore the slider value so it is not modified by RefreshValues() + if (Multiplayer.IsActive && Multiplayer.Session.StationsUI.StorageMaxChangeId != -1) + { + __instance.maxSlider.value = __state; + __instance.maxValueText.text = ((int)(__instance.maxSlider.value * 100)).ToString(); + } + eventLock = false; + } + + /* + * host behaves normally and sends update to clients which then apply the changes + * clients send a request to the server and only run the original method once they receive the response + */ + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationStorage.OnItemIconMouseDown))] + [HarmonyPriority(Priority.First)] + public static void OnItemIconMouseDown_Prefix(UIControlPanelStationStorage __instance, ref (int, int) __state) + { + __state = (__instance.station.storage[__instance.index].count, __instance.station.storage[__instance.index].inc); + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationStorage.OnItemIconMouseDown))] + [HarmonyPriority(Priority.Last)] + public static void OnItemIconMouseDown_Postfix(UIControlPanelStationStorage __instance, (int, int) __state) + { + if (!Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + var stationStore = __instance.station.storage[__instance.index]; + if (__state.Item1 == stationStore.count && __state.Item2 == stationStore.inc) + { + return; + } + var packet = new StorageUI(__instance.masterInspector.factory.planet.id, __instance.station.id, + __instance.station.gid, __instance.index, stationStore.count, stationStore.inc); + Multiplayer.Session.Network.SendPacket(packet); + } + + /* + * host behaves normally and sends update to clients which then apply the changes + * clients send a request to the server and only run the original method once they receive the response + */ + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationStorage.OnItemIconMouseUp))] + [HarmonyPriority(Priority.First)] + public static void OnItemIconMouseUp_Prefix(UIControlPanelStationStorage __instance, ref (int, int) __state) + { + __state = (__instance.station.storage[__instance.index].count, __instance.station.storage[__instance.index].inc); + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationStorage.OnItemIconMouseUp))] + [HarmonyPriority(Priority.Last)] + public static void OnItemIconMouseUp_Postfix(UIControlPanelStationStorage __instance, (int, int) __state) + { + if (!Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + var stationStore = __instance.station.storage[__instance.index]; + + if (__state.Item1 == stationStore.count && __state.Item2 == stationStore.inc) + { + return; + } + var packet = new StorageUI(__instance.masterInspector.factory.planet.id, __instance.station.id, + __instance.station.gid, __instance.index, stationStore.count, stationStore.inc); + Multiplayer.Session.Network.SendPacket(packet); + } + + /* + * sync sandbox mode lock station storage function + */ + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelStationStorage.OnKeepModeButtonClick))] + public static void OnKeepModeButtonClick_Postfix(UIControlPanelStationStorage __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.Ships.PatchLockILS) + { + return; + } + var stationStore = __instance.station.storage[__instance.index]; + + var packet = new StorageUI(__instance.masterInspector.factory.planet.id, + __instance.station.id, __instance.station.gid, __instance.index, (byte)stationStore.keepMode); + Multiplayer.Session.Network.SendPacket(packet); + } +} diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelWindow_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelWindow_Patch.cs index 927917a1f..09827f78d 100644 --- a/NebulaPatcher/Patches/Dynamic/UIControlPanelWindow_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelWindow_Patch.cs @@ -31,32 +31,29 @@ public static bool DetermineSelectionInspectorPrefix(UIControlPanelWindow __inst { if (!Multiplayer.IsActive) return true; - // In MP, open the local station window instead of inspector temporarily - // TODO: Enable Inspector in client for remote entry and sync __instance.needDetermineSelectionInspector = false; var planet = GameMain.galaxy.PlanetById(__instance.selection.astroId); var factory = planet?.factory; - if (factory == null || GameMain.localPlanet != planet) return false; switch (__instance.selection.entryType) { case EControlPanelEntryType.InterstellarStation: case EControlPanelEntryType.OrbitCollector: case EControlPanelEntryType.LocalStation: case EControlPanelEntryType.VeinCollector: - // Close station window first so it can stay on top - UIRoot.instance.uiGame.ShutStationWindow(); - var minerId = factory.entityPool[__instance.selection.objId].minerId; - var stationId = factory.entityPool[__instance.selection.objId].stationId; - UIRoot.instance.uiGame.stationWindow.veinCollectorPanel.minerId = minerId; - UIRoot.instance.uiGame.stationWindow.stationId = stationId; - if (UIRoot.instance.uiGame.inspectStationId == 0 && stationId > 0) + // Open station inspector only if the factory is loaded + if (factory == null) { - UIRoot.instance.uiGame.OpenStationWindow(); + return false; } - break; + else return true; case EControlPanelEntryType.Dispenser: - // Close station window first so it can stay on top + // In MP, temporarily disable the dispenser inspector and use the original dispenser window + if (factory == null || GameMain.localPlanet != planet) + { + return false; + } + // Close dispenser window first so it can stay on top UIRoot.instance.uiGame.ShutDispenserWindow(); var dispenserId = factory.entityPool[__instance.selection.objId].dispenserId; UIRoot.instance.uiGame.dispenserWindow.dispenserId = dispenserId; @@ -64,9 +61,9 @@ public static bool DetermineSelectionInspectorPrefix(UIControlPanelWindow __inst { UIRoot.instance.uiGame.OpenDispenserWindow(); } - break; + return false; } - return false; + return true; } [HarmonyPostfix] diff --git a/NebulaWorld/Logistics/StationUIManager.cs b/NebulaWorld/Logistics/StationUIManager.cs index fd3f629d3..8524c6676 100644 --- a/NebulaWorld/Logistics/StationUIManager.cs +++ b/NebulaWorld/Logistics/StationUIManager.cs @@ -69,17 +69,24 @@ private static void RefreshWindow(int planetId, int stationId) { // If station window is opened and viewing the updating station, refresh the window. var stationWindow = UIRoot.instance.uiGame.stationWindow; - if (stationWindow == null || !stationWindow.active) + if (stationWindow != null && stationWindow.active && + stationWindow.factory?.planetId == planetId && stationWindow.stationId == stationId) { - return; - } - if (stationWindow.factory?.planetId != planetId || stationWindow.stationId != stationId) - { - return; + using (Multiplayer.Session.StationsUI.IsIncomingRequest.On()) + { + stationWindow.OnStationIdChange(); + } } - using (Multiplayer.Session.StationsUI.IsIncomingRequest.On()) + + // If station inspector in control panel is opened and viewing the updating station, refresh the inspector. + var inspector = UIRoot.instance.uiGame.controlPanelWindow.stationInspector; + if (inspector != null && inspector.active && + inspector.factory?.planetId == planetId && inspector.stationId == stationId) { - stationWindow.OnStationIdChange(); + using (Multiplayer.Session.StationsUI.IsIncomingRequest.On()) + { + inspector.OnStationIdChange(); + } } }