diff --git a/NebulaModel/Packets/Logistics/ControlPanel/LCPAdvancedMinerEntryUpdate.cs b/NebulaModel/Packets/Logistics/ControlPanel/LCPAdvancedMinerEntryUpdate.cs new file mode 100644 index 000000000..ab4c1bfc1 --- /dev/null +++ b/NebulaModel/Packets/Logistics/ControlPanel/LCPAdvancedMinerEntryUpdate.cs @@ -0,0 +1,100 @@ +using UnityEngine; + +namespace NebulaModel.Packets.Logistics.ControlPanel; + +public class LCPAdvancedMinerEntryUpdate +{ + public LCPAdvancedMinerEntryUpdate() { } + + public void Set(int index, StationComponent station, PlanetFactory factory) + { + Index = index; + + if (!station.isCollector) + { + var powerSystem = factory.powerSystem; + var powerConsumerComponent = powerSystem.consumerPool[station.pcId]; + var networkId = powerConsumerComponent.networkId; + var powerNetwork = powerSystem.netPool[networkId]; + ConsumerRatio = (float)powerNetwork.consumerRatio; + RequirePower = (long)((powerConsumerComponent.requiredEnergy * 60L) * ConsumerRatio); + WorkEnergyPerTick = powerSystem.consumerPool[station.pcId].workEnergyPerTick; + PowerRound = station.energy / (float)station.energyMax; + } + + var minerComponent = factory.factorySystem.minerPool[station.minerId]; + if (minerComponent.id == station.minerId) + { + var veinPool = factory.veinPool; + var lowVeinCount = 0; + var emptyVeinCount = 0; + if (minerComponent.veinCount > 0) + { + for (var i = 0; i < minerComponent.veinCount; i++) + { + var id = minerComponent.veins[i]; + if (id > 0 && veinPool[id].id == id) + { + var amount = veinPool[id].amount; + if (amount < 1000) + { + if (amount > 0) + { + lowVeinCount++; + } + else + { + emptyVeinCount++; + } + } + } + } + } + VeinCount = (short)minerComponent.veinCount; + LowVeinCount = (short)lowVeinCount; + EmptyVeinCount = (short)emptyVeinCount; + + var veinId = ((minerComponent.veinCount == 0) ? 0 : minerComponent.veins[minerComponent.currentVeinIndex]); + VeinProtoId = (int)veinPool[veinId].type; + var veinProto = LDB.veins.Select((int)veinPool[veinId].type); + if (veinProto != null) + { + minerComponent.GetTotalVeinAmount(veinPool); + TotalVeinAmount = minerComponent.totalVeinAmount; + } + } + + ItemId = 0; + if (station.storage == null || station.storage.Length == 0) return; + ref var store = ref station.storage[0]; + ItemId = store.itemId; + ItemCount = store.count; + LocalOrder = (short)Mathf.Clamp(store.localOrder, -20000, 20000); + RemoteOrder = (short)Mathf.Clamp(store.remoteOrder, -20000, 20000); + StoreMax = store.max; + LocalLogic = (byte)store.localLogic; + RemoteLogic = (byte)store.remoteLogic; + } + + public static readonly LCPAdvancedMinerEntryUpdate Instance = new(); + + public int Index { get; set; } + public float ConsumerRatio { get; set; } + public long RequirePower { get; set; } + public long WorkEnergyPerTick { get; set; } + public float PowerRound { get; set; } + + public int VeinProtoId { get; set; } + public long TotalVeinAmount { get; set; } + public short VeinCount { get; set; } + public short LowVeinCount { get; set; } + public short EmptyVeinCount { get; set; } + + public int ItemId { get; set; } + public int ItemCount { get; set; } + public short LocalOrder { get; set; } + public short RemoteOrder { get; set; } + public int StoreMax { get; set; } + public byte LocalLogic { get; set; } + public byte RemoteLogic { get; set; } +} diff --git a/NebulaModel/Packets/Logistics/ControlPanel/LCPDispenserEntryUpdate.cs b/NebulaModel/Packets/Logistics/ControlPanel/LCPDispenserEntryUpdate.cs new file mode 100644 index 000000000..04a88be76 --- /dev/null +++ b/NebulaModel/Packets/Logistics/ControlPanel/LCPDispenserEntryUpdate.cs @@ -0,0 +1,82 @@ +namespace NebulaModel.Packets.Logistics.ControlPanel; + +public class LCPDispenserEntryUpdate +{ + public LCPDispenserEntryUpdate() { } + + public void Set(int index, DispenserComponent dispenser, PlanetFactory factory) + { + Index = index; + + var powerSystem = factory.powerSystem; + var powerConsumerComponent = powerSystem.consumerPool[dispenser.pcId]; + var networkId = powerConsumerComponent.networkId; + var powerNetwork = powerSystem.netPool[networkId]; + ConsumerRatio = (float)powerNetwork.consumerRatio; + RequirePower = (long)((powerConsumerComponent.requiredEnergy * 60L) * ConsumerRatio); + WorkEnergyPerTick = powerSystem.consumerPool[dispenser.pcId].workEnergyPerTick; + PowerRound = dispenser.energy / (float)dispenser.energyMax; + + Filter = dispenser.filter; + PlayerMode = (short)dispenser.playerMode; + StorageMode = (short)dispenser.storageMode; + IdleCourierCount = dispenser.idleCourierCount; + WorkCourierCount = dispenser.workCourierCount; + + var status = 0; + if (dispenser.playerMode == EPlayerDeliveryMode.None && dispenser.storageMode == EStorageDeliveryMode.None) + { + status = 1; + } + else if (dispenser.filter == 0) + { + status = 2; + } + else if (dispenser.idleCourierCount + dispenser.workCourierCount == 0) + { + status = 3; + } + else if (dispenser.holdupItemCount > 0) + { + status = 5; + } + else if (ConsumerRatio < 0.0001f && dispenser.energy < 100000L) + { + status = 4; + } + WarningFlag = status > 0; + + var count = 0; + var inc = 0; + var loop = 0; + if (dispenser.storage != null && dispenser.filter > 0) + { + var storageComponent = dispenser.storage; + do + { + count += storageComponent.GetItemCount(dispenser.filter, out var num); + inc += num; + storageComponent = storageComponent.previousStorage; + if (loop++ > 20) break; + } + while (storageComponent != null); + } + ItemCount = count; + } + + public static readonly LCPDispenserEntryUpdate Instance = new(); + + public int Index { get; set; } + public float ConsumerRatio { get; set; } + public long RequirePower { get; set; } + public long WorkEnergyPerTick { get; set; } + public float PowerRound { get; set; } + + public int Filter { get; set; } + public short PlayerMode { get; set; } + public short StorageMode { get; set; } + public int IdleCourierCount { get; set; } + public int WorkCourierCount { get; set; } + public bool WarningFlag { get; set; } + public int ItemCount { get; set; } +} diff --git a/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsRequest.cs b/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsRequest.cs new file mode 100644 index 000000000..74ff5fa1f --- /dev/null +++ b/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsRequest.cs @@ -0,0 +1,41 @@ +using System; +using NebulaAPI.DataStructures; + +namespace NebulaModel.Packets.Logistics.ControlPanel; + +public class LCPFilterResultsRequest +{ + public LCPFilterResultsRequest() { } + + public LCPFilterResultsRequest(in ControlPanelFilter controlPanelFilter) + { + TypeFilter = (int)controlPanelFilter.typeFilter; + AstorFilter = controlPanelFilter.astroFilter; + if (controlPanelFilter.itemsFilter != null) + { + ItemsFilter = new int[controlPanelFilter.itemsFilter.Length]; + Array.Copy(controlPanelFilter.itemsFilter, ItemsFilter, ItemsFilter.Length); + } + else + { + ItemsFilter = new int[0]; + } + StateFilter = controlPanelFilter.stateFilter; + SearchFilter = controlPanelFilter.searchFilter; + SortMethod = (short)controlPanelFilter.sortMethod; + + LocalPlanetAstroId = GameMain.data.localPlanet?.astroId ?? 0; + LocalStarAstroId = GameMain.data.localStar?.astroId ?? 0; + PlayerUposition = new Float3(GameMain.mainPlayer.uPosition); + } + + public int TypeFilter { get; set; } + public int AstorFilter { get; set; } + public int[] ItemsFilter { get; set; } + public int StateFilter { get; set; } + public string SearchFilter { get; set; } + public short SortMethod { get; set; } + public int LocalPlanetAstroId { get; set; } + public int LocalStarAstroId { get; set; } + public Float3 PlayerUposition { get; set; } +} diff --git a/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsResponse.cs b/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsResponse.cs new file mode 100644 index 000000000..376e95729 --- /dev/null +++ b/NebulaModel/Packets/Logistics/ControlPanel/LCPFilterResultsResponse.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +namespace NebulaModel.Packets.Logistics.ControlPanel; + +public class LCPFilterResultsResponse +{ + public LCPFilterResultsResponse() { } + + public LCPFilterResultsResponse(List sortedAstros, List targets) + { + SortedAstroIds = new int[sortedAstros.Count]; + for (var i = 0; i < sortedAstros.Count; i++) + { + SortedAstroIds[i] = sortedAstros[i].astroId; + } + + var resultTargetCount = targets.Count; + ObjTypes = new short[resultTargetCount]; + ObjIds = new int[resultTargetCount]; + AstroIds = new int[resultTargetCount]; + EntryTypes = new short[resultTargetCount]; + for (var i = 0; i < resultTargetCount; i++) + { + var target = targets[i]; + ObjTypes[i] = (short)target.objType; + ObjIds[i] = target.objId; + AstroIds[i] = target.astroId; + EntryTypes[i] = (short)target.entryType; + } + } + + public int[] SortedAstroIds { get; set; } + public short[] ObjTypes { get; set; } + public int[] ObjIds { get; set; } + public int[] AstroIds { get; set; } + public short[] EntryTypes { get; set; } +} diff --git a/NebulaModel/Packets/Logistics/ControlPanel/LCPObjectEntryEntityInfo.cs b/NebulaModel/Packets/Logistics/ControlPanel/LCPObjectEntryEntityInfo.cs new file mode 100644 index 000000000..0651064d3 --- /dev/null +++ b/NebulaModel/Packets/Logistics/ControlPanel/LCPObjectEntryEntityInfo.cs @@ -0,0 +1,21 @@ +namespace NebulaModel.Packets.Logistics.ControlPanel; + +public class LCPObjectEntryEntityInfo +{ + public LCPObjectEntryEntityInfo() { } + + public void Set(int index, int protoId, int id, string name) + { + Index = index; + ProtoId = protoId; + Id = id; + Name = name; + } + + public static readonly LCPObjectEntryEntityInfo Instance = new(); + + public int Index { get; set; } + public int ProtoId { get; set; } + public int Id { get; set; } + public string Name { get; set; } +} diff --git a/NebulaModel/Packets/Logistics/ControlPanel/LCPObjectEntryRequest.cs b/NebulaModel/Packets/Logistics/ControlPanel/LCPObjectEntryRequest.cs new file mode 100644 index 000000000..e327f7b4f --- /dev/null +++ b/NebulaModel/Packets/Logistics/ControlPanel/LCPObjectEntryRequest.cs @@ -0,0 +1,23 @@ +namespace NebulaModel.Packets.Logistics.ControlPanel; + +public class LCPObjectEntryRequest +{ + public LCPObjectEntryRequest() { } + + public void Set(UIControlPanelObjectEntry controlPanelFilter, bool isInit = false) + { + // isInit: Request for entityData.protoId, name + Index = controlPanelFilter.index; + EntryType = (short)controlPanelFilter.entryType; + AstroId = controlPanelFilter.target.astroId; + // Use sign of ObjId to note the state of request + ObjId = isInit ? -controlPanelFilter.target.objId : controlPanelFilter.target.objId; + } + + public static readonly LCPObjectEntryRequest Instance = new(); + + public int Index { get; set; } + public short EntryType { get; set; } + public int AstroId { get; set; } + public int ObjId { get; set; } +} diff --git a/NebulaModel/Packets/Logistics/ControlPanel/LCPStationEntryUpdate.cs b/NebulaModel/Packets/Logistics/ControlPanel/LCPStationEntryUpdate.cs new file mode 100644 index 000000000..161cb2ee0 --- /dev/null +++ b/NebulaModel/Packets/Logistics/ControlPanel/LCPStationEntryUpdate.cs @@ -0,0 +1,93 @@ +using UnityEngine; + +namespace NebulaModel.Packets.Logistics.ControlPanel; + +public class LCPStationEntryUpdate +{ + public LCPStationEntryUpdate() { } + + public void Set(int index, StationComponent station, PlanetFactory factory) + { + Index = index; + + if (!station.isCollector) + { + var powerSystem = factory.powerSystem; + var powerConsumerComponent = powerSystem.consumerPool[station.pcId]; + var networkId = powerConsumerComponent.networkId; + var powerNetwork = powerSystem.netPool[networkId]; + ConsumerRatio = (float)powerNetwork.consumerRatio; + RequirePower = (long)((powerConsumerComponent.requiredEnergy * 60L) * ConsumerRatio); + WorkEnergyPerTick = powerSystem.consumerPool[station.pcId].workEnergyPerTick; + PowerRound = station.energy / (float)station.energyMax; + } + else + { + ConsumerRatio = 1.0f; + RequirePower = 0; + WorkEnergyPerTick = 0; + PowerRound = 0; + } + + IdleDroneCount = (short)station.idleDroneCount; + WorkDroneCount = (short)station.workDroneCount; + IdleShipCount = (short)station.idleShipCount; + WorkShipCount = (short)station.workShipCount; + WarperCount = (short)station.warperCount; + + if (ItemId == null) + { + ItemId = new int[5]; + ItemCount = new int[5]; + LocalOrder = new short[5]; + RemoteOrder = new short[5]; + StoreMax = new int[5]; + LocalLogic = new byte[5]; + RemoteLogic = new byte[5]; + } + var i = 0; + if (station.storage != null) + { + var storeLength = station.storage.Length; + if (storeLength > 5) storeLength = 5; + for (; i < storeLength; i++) + { + ref var store = ref station.storage[i]; + ItemId[i] = store.itemId; + ItemCount[i] = store.count; + LocalOrder[i] = (short)Mathf.Clamp(store.localOrder, -20000, 20000); + RemoteOrder[i] = (short)Mathf.Clamp(store.remoteOrder, -20000, 20000); + StoreMax[i] = store.max; + LocalLogic[i] = (byte)store.localLogic; + RemoteLogic[i] = (byte)store.remoteLogic; + } + } + for (; i < 5; i++) + { + ItemId[i] = 0; + ItemCount[i] = 0; + } + } + + public static readonly LCPStationEntryUpdate Instance = new(); + + public int Index { get; set; } + public float ConsumerRatio { get; set; } + public long RequirePower { get; set; } + public long WorkEnergyPerTick { get; set; } + public float PowerRound { get; set; } + + public short IdleDroneCount { get; set; } + public short WorkDroneCount { get; set; } + public short IdleShipCount { get; set; } + public short WorkShipCount { get; set; } + public short WarperCount { get; set; } + + public int[] ItemId { get; set; } + public int[] ItemCount { get; set; } + public short[] LocalOrder { get; set; } + public short[] RemoteOrder { get; set; } + public int[] StoreMax { get; set; } + public byte[] LocalLogic { get; set; } + public byte[] RemoteLogic { get; set; } +} diff --git a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPAdvancedMinerEntryUpdateProcessor.cs b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPAdvancedMinerEntryUpdateProcessor.cs new file mode 100644 index 000000000..e87e42c4b --- /dev/null +++ b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPAdvancedMinerEntryUpdateProcessor.cs @@ -0,0 +1,137 @@ +#region + +using NebulaAPI.Packets; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.Logistics.ControlPanel; +using UnityEngine; + +#endregion + +namespace NebulaNetwork.PacketProcessors.Logistics.ControlPanel; + +[RegisterPacketProcessor] +public class LCPAdvancedMinerEntryUpdateProcessor : PacketProcessor +{ + static readonly StationStore[] stationStores = new StationStore[1]; + + protected override void ProcessPacket(LCPAdvancedMinerEntryUpdate packet, NebulaConnection conn) + { + if (IsHost) return; + + var objectEntryPool = UIRoot.instance.uiGame.controlPanelWindow.objectEntryPool; + for (var i = 0; i < objectEntryPool.Count; i++) + { + if (objectEntryPool[i] != null && objectEntryPool[i].index == packet.Index) + { + var entry = objectEntryPool[i] as UIControlPanelAdvancedMinerEntry; + UpdateEntry(entry, packet); + return; + } + } + } + + private static void UpdateEntry(UIControlPanelAdvancedMinerEntry entry, LCPAdvancedMinerEntryUpdate packet) + { + if (entry == null) return; + + // Modify from UIControlPanelAdvancedMinerEntry._OnUpdate + var isInfiniteResource = GameMain.data.gameDesc.isInfiniteResource; + var isAllEmpty = packet.VeinCount == packet.EmptyVeinCount; + entry.warningItemCanvasGroup.alpha = ((packet.LowVeinCount > 0 && !isInfiniteResource) || isAllEmpty) ? 1 : 0; + entry.warningText.text = (isAllEmpty ? "矿脉全部耗尽警告".Translate() : string.Format("矿脉耗尽警告".Translate(), packet.LowVeinCount)); + + var veinProto = LDB.veins.Select(packet.VeinProtoId); + if (!isAllEmpty && veinProto != null) + { + entry.minerItemImage.sprite = veinProto.iconSprite; + entry.minerItemImage.color = Color.white; + StringBuilderUtility.WriteKMG(entry.veinAmountSB, 8, packet.TotalVeinAmount, false); + entry.veinAmountText.text = (isInfiniteResource ? ("(" + packet.VeinCount + ")") : string.Concat(new object[] + { + entry.veinAmountSB.ToString(), + "(", + packet.VeinCount, + ")" + })); + } + else + { + entry.minerItemImage.sprite = null; + entry.minerItemImage.color = Color.clear; + entry.veinAmountText.text = ""; + } + + // Update item UI + ref var store = ref stationStores[0]; + store.itemId = packet.ItemId; + store.count = packet.ItemCount; + store.localOrder = packet.LocalOrder; + store.remoteOrder = packet.RemoteOrder; + store.max = packet.StoreMax; + store.localLogic = (ELogisticStorage)packet.LocalLogic; + store.remoteLogic = (ELogisticStorage)packet.RemoteLogic; + var tmp = entry.station.storage; + entry.station.storage = stationStores; + // expand UpdateItems() + entry.storageItem.SetVisible(stationStores[0].itemId > 0); + entry.storageItem._Update(); + entry.station.storage = tmp; + + // Update power UI + entry.powerGroupGo.SetActive(true); + var consumerRatio = (float)packet.ConsumerRatio; + int powerStatusCode; + if (consumerRatio >= 1f) + { + entry.powerCircleFg.fillAmount = 1f; + powerStatusCode = 1; + } + else + { + entry.powerCircleFg.fillAmount = consumerRatio; + powerStatusCode = ((consumerRatio >= 0.1f) ? 2 : 3); + } + StringBuilderUtility.WriteKMG1000(entry.sbw, 8, packet.RequirePower, true); + StringBuilderUtility.WriteKMG1000(entry.sbw2, 8, packet.WorkEnergyPerTick * 60L, true); + entry.powerText.text = entry.sbw.ToString(); + entry.maxChargePowerValue.text = entry.sbw2.ToString(); + entry.powerRoundFg.fillAmount = packet.PowerRound; + switch (powerStatusCode) + { + + case 1: + entry.powerSignImage.color = entry.masterWindow.powerSignColor1; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor1; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor1; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor1; + entry.powerText.color = entry.masterWindow.powerTextColor1; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor1; + break; + case 2: + entry.powerSignImage.color = entry.masterWindow.powerSignColor2; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor2; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor2; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor2; + entry.powerText.color = entry.masterWindow.powerTextColor2; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor2; + break; + case 3: + entry.powerSignImage.color = entry.masterWindow.powerSignColor3; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor3; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor3; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor3; + entry.powerText.color = entry.masterWindow.powerTextColor3; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor3; + break; + default: + entry.powerSignImage.color = entry.masterWindow.powerSignColor0; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor0; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor0; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor0; + entry.powerText.color = entry.masterWindow.powerTextColor0; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor0; + break; + } + } +} diff --git a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPDispenserEntryUpdateProcessor.cs b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPDispenserEntryUpdateProcessor.cs new file mode 100644 index 000000000..7bc9d2d17 --- /dev/null +++ b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPDispenserEntryUpdateProcessor.cs @@ -0,0 +1,130 @@ +#region + +using NebulaAPI.Packets; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.Logistics.ControlPanel; +using UnityEngine; + +#endregion + +namespace NebulaNetwork.PacketProcessors.Logistics.ControlPanel; + +[RegisterPacketProcessor] +public class LCPDispenserEntryUpdateProcessor : PacketProcessor +{ + protected override void ProcessPacket(LCPDispenserEntryUpdate packet, NebulaConnection conn) + { + if (IsHost) return; + + var objectEntryPool = UIRoot.instance.uiGame.controlPanelWindow.objectEntryPool; + for (var i = 0; i < objectEntryPool.Count; i++) + { + if (objectEntryPool[i] != null && objectEntryPool[i].index == packet.Index) + { + var entry = objectEntryPool[i] as UIControlPanelDispenserEntry; + UpdateEntry(entry, packet); + return; + } + } + } + + private static void UpdateEntry(UIControlPanelDispenserEntry entry, LCPDispenserEntryUpdate packet) + { + if (entry == null) return; + + // Modify from UIControlPanelDispenserEntry._OnUpdate + var filter = packet.Filter; + var playerMode = (EPlayerDeliveryMode)packet.PlayerMode; + var storageMode = (EStorageDeliveryMode)packet.StorageMode; + + if (playerMode == EPlayerDeliveryMode.Recycle && filter < 0) + { + entry.transitItemGroup.alpha = 0f; + entry.transitItemGroup.blocksRaycasts = false; + entry.recycleAllText.color = entry.masterWindow.recycleAllColor; + } + else + { + entry.transitItemGroup.alpha = 1f; + entry.transitItemGroup.blocksRaycasts = true; + entry.transitItemText.color = entry.masterWindow.transitItemTextColor; + entry.recycleAllText.color = Color.clear; + var itemProto = LDB.items.Select(filter); + if (itemProto != null) + { + entry.transitItemImage.sprite = itemProto.iconSprite; + entry.transitItemButton.tips.itemId = filter; + entry.transitItemButton.tips.itemInc = 0; + entry.transitItemButton.tips.itemCount = 0; + entry.transitItemButton.tips.type = UIButton.ItemTipType.Other; + entry.transitItemText.text = packet.ItemCount.ToString(); + } + else + { + entry.transitItemGroup.alpha = 0f; + entry.transitItemGroup.blocksRaycasts = false; + entry.recycleAllText.color = Color.clear; + } + } + entry.SetPlayerDeliveryActiveModes(playerMode, entry.mechaDeliverySupply, entry.mechaDeliveryDemand, entry.mechaDeliverySupplyDemand); + entry.SetStorageDeliveryActiveModes(storageMode, entry.storageDeliverySupply, entry.storageDeliveryDemand); + entry.courierCountText.text = packet.IdleCourierCount.ToString() + "/" + (packet.IdleCourierCount + packet.WorkCourierCount).ToString(); + + // Update power UI + var consumerRatio = (float)packet.ConsumerRatio; + int powerStatusCode; + if (consumerRatio >= 1f) + { + entry.powerCircleFg.fillAmount = 1f; + powerStatusCode = 1; + } + else + { + entry.powerCircleFg.fillAmount = consumerRatio; + powerStatusCode = ((consumerRatio >= 0.1f) ? 2 : 3); + } + StringBuilderUtility.WriteKMG1000(entry.sbw, 8, packet.RequirePower, true); + StringBuilderUtility.WriteKMG1000(entry.sbw2, 8, packet.WorkEnergyPerTick * 60L, true); + entry.powerText.text = entry.sbw.ToString(); + entry.maxChargePowerValue.text = entry.sbw2.ToString(); + entry.powerRoundFg.fillAmount = packet.PowerRound; + switch (powerStatusCode) + { + + case 1: + entry.powerSignImage.color = entry.masterWindow.powerSignColor1; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor1; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor1; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor1; + entry.powerText.color = entry.masterWindow.powerTextColor1; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor1; + break; + case 2: + entry.powerSignImage.color = entry.masterWindow.powerSignColor2; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor2; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor2; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor2; + entry.powerText.color = entry.masterWindow.powerTextColor2; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor2; + break; + case 3: + entry.powerSignImage.color = entry.masterWindow.powerSignColor3; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor3; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor3; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor3; + entry.powerText.color = entry.masterWindow.powerTextColor3; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor3; + break; + default: + entry.powerSignImage.color = entry.masterWindow.powerSignColor0; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor0; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor0; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor0; + entry.powerText.color = entry.masterWindow.powerTextColor0; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor0; + break; + } + entry.warningItemCanvasGroup.alpha = packet.WarningFlag ? 1 : 0; + } +} diff --git a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsRequestProcessor.cs b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsRequestProcessor.cs new file mode 100644 index 000000000..95ca5d169 --- /dev/null +++ b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsRequestProcessor.cs @@ -0,0 +1,191 @@ +#region + +using System; +using System.Collections.Generic; +using NebulaAPI.Packets; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.Logistics.ControlPanel; + +#endregion + +namespace NebulaNetwork.PacketProcessors.Logistics.ControlPanel; + +[RegisterPacketProcessor] +public class LCPFilterResultsRequestProcessor : PacketProcessor +{ + protected override void ProcessPacket(LCPFilterResultsRequest packet, NebulaConnection conn) + { + if (IsClient) return; + + // Modify from UIControlPanelWindow.DetermineFilterResults + // Send back the filter result from client's request + + var filter = new ControlPanelFilter + { + typeFilter = (ControlPanelFilter.EEntryFilter)packet.TypeFilter, + astroFilter = packet.AstorFilter, + itemsFilter = packet.ItemsFilter, + stateFilter = packet.StateFilter, + searchFilter = packet.SearchFilter, + sortMethod = (ControlPanelFilter.ESortMethod)packet.SortMethod + }; + + List sortedAstros = []; + List targets = []; + + + var factoryCount = GameMain.data.factoryCount; + var localPlanetAstroId = packet.LocalPlanetAstroId; + var localStarAstroId = packet.LocalStarAstroId; + ref var ptr = ref GameMain.data.mainPlayer.uPosition; + + var factories = GameMain.data.factories; + var galaxyAstros = GameMain.data.spaceSector.galaxyAstros; + for (var i = 0; i < factoryCount; i++) + { + var astroId = factories[i].planet.astroId; + if (filter.sortMethod == ControlPanelFilter.ESortMethod.AstroDistance) + { + var sqrMagnitude = (galaxyAstros[astroId].uPos - ptr).sqrMagnitude; + var index = sortedAstros.Count - 1; + while (index >= 0 && sqrMagnitude < sortedAstros[index].sqrDistToPlayer) + { + index--; + } + sortedAstros.Insert(index + 1, new ControlPanelAstroData(astroId, sqrMagnitude)); + } + else + { + sortedAstros.Add(new ControlPanelAstroData(astroId)); + } + } + + var hasStationType = filter.hasStationType; + var flag1 = (filter.typeFilter & ControlPanelFilter.EEntryFilter.InterstellarStation) > ControlPanelFilter.EEntryFilter.None; + var flag2 = (filter.typeFilter & ControlPanelFilter.EEntryFilter.OrbitCollector) > ControlPanelFilter.EEntryFilter.None; + var flag3 = (filter.typeFilter & ControlPanelFilter.EEntryFilter.LocalStation) > ControlPanelFilter.EEntryFilter.None; + var flag4 = (filter.typeFilter & ControlPanelFilter.EEntryFilter.VeinCollector) > ControlPanelFilter.EEntryFilter.None; + var flag5 = (filter.typeFilter & (ControlPanelFilter.EEntryFilter.LocalStation | ControlPanelFilter.EEntryFilter.VeinCollector)) > ControlPanelFilter.EEntryFilter.None; + var flag6 = !flag5; + var flag7 = (filter.typeFilter & ControlPanelFilter.EEntryFilter.Dispenser) > ControlPanelFilter.EEntryFilter.None; + var flag8 = !string.IsNullOrWhiteSpace(filter.searchFilter); + var num3 = 0; + var flag9 = flag8 && int.TryParse(filter.searchFilter, out num3); + var flag10 = filter.stateFilter != -1; + var hasItemFilter = filter.hasItemFilter; + + var astrosFactory = GameMain.data.galaxy.astrosFactory; + for (var j = 0; j < sortedAstros.Count; j++) + { + var planetFactory = astrosFactory[sortedAstros[j].astroId]; + if (planetFactory != null) + { + var planet = planetFactory.planet; + if (planet != null && (filter.astroFilter == -1 || (filter.astroFilter == 0 && (planet.astroId == localPlanetAstroId || (localPlanetAstroId == 0 && planet.star.astroId == localStarAstroId))) || filter.astroFilter == planet.astroId || filter.astroFilter == planet.star.astroId)) + { + var controlPanelTarget = new ControlPanelTarget(EObjectType.None, 0, planet.astroId, EControlPanelEntryType.None); + targets.Add(controlPanelTarget); + var count = targets.Count; + if (hasStationType) + { + var stationPool = planetFactory.transport.stationPool; + var stationCursor = planetFactory.transport.stationCursor; + var entityPool = planetFactory.entityPool; + var buffer = planetFactory.digitalSystem.extraInfoes.buffer; + for (var k = 1; k < stationCursor; k++) + { + var stationComponent = stationPool[k]; + if (stationComponent != null && stationComponent.id == k) + { + var econtrolPanelEntryType = (stationComponent.isStellar ? (stationComponent.isCollector ? EControlPanelEntryType.OrbitCollector : EControlPanelEntryType.InterstellarStation) : (stationComponent.isVeinCollector ? EControlPanelEntryType.VeinCollector : EControlPanelEntryType.LocalStation)); + if ((flag1 && econtrolPanelEntryType == EControlPanelEntryType.InterstellarStation) || (flag2 && econtrolPanelEntryType == EControlPanelEntryType.OrbitCollector) || (flag3 && econtrolPanelEntryType == EControlPanelEntryType.LocalStation) || (flag4 && econtrolPanelEntryType == EControlPanelEntryType.VeinCollector)) + { + var flag12 = true; + if (flag8) + { + flag12 = flag9 && stationComponent.id == num3; + if (!flag12) + { + var extraInfoId = entityPool[stationComponent.entityId].extraInfoId; + if (extraInfoId > 0) + { + var info = buffer[extraInfoId].info; + if (!string.IsNullOrEmpty(info) && info.IndexOf(filter.searchFilter, StringComparison.OrdinalIgnoreCase) >= 0) + { + flag12 = true; + } + } + } + } + if (flag12) + { + var flag13 = true; + if (hasItemFilter || flag10) + { + var storage = stationComponent.storage; + flag13 = false; + for (var l = 0; l < storage.Length; l++) + { + if ((!hasItemFilter || filter.ItemFilterPass(storage[l].itemId)) && (!flag10 || (storage[l].itemId > 0 && ((flag6 && storage[l].remoteLogic == (ELogisticStorage)filter.stateFilter) || (flag5 && storage[l].localLogic == (ELogisticStorage)filter.stateFilter))))) + { + flag13 = true; + break; + } + } + } + if (flag13) + { + var controlPanelTarget2 = new ControlPanelTarget(EObjectType.None, stationComponent.entityId, planet.astroId, econtrolPanelEntryType); + targets.Add(controlPanelTarget2); + } + } + } + } + } + } + if (flag7) + { + var dispenserPool = planetFactory.transport.dispenserPool; + var dispenserCursor = planetFactory.transport.dispenserCursor; + for (var m = 1; m < dispenserCursor; m++) + { + var dispenserComponent = dispenserPool[m]; + if (dispenserComponent != null && dispenserComponent.id == m) + { + var flag14 = true; + if (flag8 && flag9) + { + flag14 = dispenserComponent.id == num3; + } + if (flag14) + { + var flag15 = true; + if (hasItemFilter || flag10) + { + flag15 = false; + if ((!hasItemFilter || filter.ItemFilterPass(dispenserComponent.filter) || (dispenserComponent.filter < 0 && dispenserComponent.playerMode == EPlayerDeliveryMode.Recycle)) && (!flag10 || (dispenserComponent.storageMode > EStorageDeliveryMode.None && (filter.stateFilter == 0 || filter.stateFilter == (int)dispenserComponent.storageMode)) || (dispenserComponent.playerMode > EPlayerDeliveryMode.None && filter.stateFilter - (int)dispenserComponent.playerMode - 9 <= 2))) + { + flag15 = true; + } + } + if (flag15) + { + var controlPanelTarget3 = new ControlPanelTarget(EObjectType.None, dispenserComponent.entityId, planet.astroId, EControlPanelEntryType.Dispenser); + targets.Add(controlPanelTarget3); + } + } + } + } + } + if (targets.Count == count) + { + targets.RemoveAt(targets.Count - 1); + } + } + } + } + + conn.SendPacket(new LCPFilterResultsResponse(sortedAstros, targets)); + } +} diff --git a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsResponseProcessor.cs b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsResponseProcessor.cs new file mode 100644 index 000000000..ef20aea50 --- /dev/null +++ b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPFilterResultsResponseProcessor.cs @@ -0,0 +1,52 @@ +#region + +using NebulaAPI.Packets; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.Logistics.ControlPanel; + +#endregion + +namespace NebulaNetwork.PacketProcessors.Logistics.ControlPanel; + +[RegisterPacketProcessor] +public class LCPFilterResultsResponseProcessor : PacketProcessor +{ + protected override void ProcessPacket(LCPFilterResultsResponse packet, NebulaConnection conn) + { + if (IsHost) return; + + // Modify from UIControlPanelWindow.DetermineFilterResults + // Set sortedAstros and AddFilterResult by the response + + var window = UIRoot.instance.uiGame.controlPanelWindow; + window.ResetObjectEntryPool(); + window.ClearFilterResults(); + window.sortedAstros.Clear(); + foreach (var astroId in packet.SortedAstroIds) + { + window.sortedAstros.Add(new ControlPanelAstroData(astroId)); + } + + var localPlanetId = GameMain.data.localPlanet?.astroId ?? 0; + var resultCount = packet.EntryTypes.Length; + for (var i = 0; i < resultCount; i++) + { + var controlPanelTarget = new ControlPanelTarget + { + objType = (EObjectType)packet.ObjTypes[i], + objId = packet.ObjIds[i], + astroId = packet.AstroIds[i], + entryType = (EControlPanelEntryType)packet.EntryTypes[i] + }; + + var visible = ((localPlanetId == controlPanelTarget.astroId) ? (!window.astroExpands.Contains(0)) : window.astroExpands.Contains(controlPanelTarget.astroId)); + if (controlPanelTarget.entryType == EControlPanelEntryType.Planet) visible = true; + window.AddFilterResult(ref controlPanelTarget, visible); + } + window.resultGeneration++; + window.needDetermineEntryVisible = true; + window.needDetermineFilterResults = false; + window.ReconnSelectionOnDetermineResults(); + } +} diff --git a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPObjectEntryEntityInfoProcessor.cs b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPObjectEntryEntityInfoProcessor.cs new file mode 100644 index 000000000..8818786bd --- /dev/null +++ b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPObjectEntryEntityInfoProcessor.cs @@ -0,0 +1,111 @@ +#region + +using NebulaAPI.Packets; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.Logistics.ControlPanel; +using UITools; +using UnityEngine; + +#endregion + +namespace NebulaNetwork.PacketProcessors.Logistics.ControlPanel; + +[RegisterPacketProcessor] +public class LCPObjectEntryEntityInfoProcessor : PacketProcessor +{ + protected override void ProcessPacket(LCPObjectEntryEntityInfo packet, NebulaConnection conn) + { + if (IsHost) return; + + var objectEntryPool = UIRoot.instance.uiGame.controlPanelWindow.objectEntryPool; + for (var i = 0; i < objectEntryPool.Count; i++) + { + if (objectEntryPool[i] != null && objectEntryPool[i].index == packet.Index) + { + UpdateEntry(objectEntryPool[i], packet); + return; + } + } + } + + private static void UpdateEntry(UIControlPanelObjectEntry objectEntry, LCPObjectEntryEntityInfo packet) + { + if (objectEntry == null) return; + + if (objectEntry is UIControlPanelStationEntry) + { + var entry = objectEntry as UIControlPanelStationEntry; + + entry.storageItem0.station = entry.station; + entry.storageItem1.station = entry.station; + entry.storageItem2.station = entry.station; + entry.storageItem3.station = entry.station; + entry.storageItem4.station = entry.station; + var itemProto = LDB.items.Select(packet.ProtoId); + entry.stationIcon.sprite = itemProto?.iconSprite; + entry.stationIdText.text = "#" + packet.Id; + entry.stationIconButton.tips.itemId = packet.ProtoId; + entry.stationIconButton.tips.itemInc = 0; + entry.stationIconButton.tips.itemCount = 0; + entry.stationIconButton.tips.type = UIButton.ItemTipType.Other; + + entry.id = packet.Id; + var text = "无名称编号".Translate(); + if (packet.Name == "") + { + text = string.Format(text, entry.id.ToString()); + entry.stationNameText.color = entry.masterWindow.unnamedColor; + } + else + { + text = packet.Name; + entry.stationNameText.color = entry.masterWindow.renamedColor; + } + Utils.UITextTruncateShow(entry.stationNameText, text, entry.stationNameTextWidthLimit, ref entry.stationNameTextSettings); + } + else if (objectEntry is UIControlPanelAdvancedMinerEntry) + { + var entry = objectEntry as UIControlPanelAdvancedMinerEntry; + + entry.storageItem.station = entry.station; + var itemProto = LDB.items.Select(packet.ProtoId); + entry.stationIcon.sprite = (itemProto?.iconSprite); + entry.stationIdText.text = "#" + packet.Id; + entry.stationIconButton.tips.itemId = packet.ProtoId; + entry.stationIconButton.tips.itemInc = 0; + entry.stationIconButton.tips.itemCount = 0; + entry.stationIconButton.tips.type = UIButton.ItemTipType.Other; + + entry.id = packet.Id; + var text = "无名称编号".Translate(); + if (packet.Name == "") + { + text = string.Format(text, entry.id.ToString()); + entry.stationNameText.color = entry.masterWindow.unnamedColor; + } + else + { + text = packet.Name; + entry.stationNameText.color = entry.masterWindow.renamedColor; + } + Utils.UITextTruncateShow(entry.stationNameText, text, entry.stationNameTextWidthLimit, ref entry.stationNameTextSettings); + } + else if (objectEntry is UIControlPanelDispenserEntry) + { + var entry = objectEntry as UIControlPanelDispenserEntry; + + entry.id = packet.Id; + var itemProto = LDB.items.Select(packet.ProtoId); + entry.dispenserIcon.sprite = itemProto?.iconSprite; + entry.dispenserIdText.text = "#" + entry.id.ToString(); + entry.dispenserIconButton.tips.itemId = packet.ProtoId; + entry.dispenserIconButton.tips.itemInc = 0; + entry.dispenserIconButton.tips.itemCount = 0; + entry.dispenserIconButton.tips.type = UIButton.ItemTipType.Other; + + var text = "无名称编号".Translate(); + entry.dispenserNameText.text = string.Format(text, entry.id.ToString()); + } + } +} diff --git a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPObjectEntryRequestProcessor.cs b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPObjectEntryRequestProcessor.cs new file mode 100644 index 000000000..57111261a --- /dev/null +++ b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPObjectEntryRequestProcessor.cs @@ -0,0 +1,74 @@ +#region + +using NebulaAPI.Packets; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.Logistics.ControlPanel; +using UnityEngine; + +#endregion + +namespace NebulaNetwork.PacketProcessors.Logistics.ControlPanel; + +[RegisterPacketProcessor] +public class LCPObjectEntryRequestProcessor : PacketProcessor +{ + protected override void ProcessPacket(LCPObjectEntryRequest packet, NebulaConnection conn) + { + if (IsClient) return; + var factory = GameMain.galaxy.PlanetById(packet.AstroId)?.factory; + if (factory == null) return; + + var isInit = false; + var objId = packet.ObjId; + if (objId < 0) + { + objId = -objId; + isInit = true; + } + if (objId <= 0 || objId > factory.entityPool.Length) return; + ref var entity = ref factory.entityPool[objId]; + if (entity.id != objId) return; + + switch ((EControlPanelEntryType)packet.EntryType) + { + case EControlPanelEntryType.InterstellarStation: + case EControlPanelEntryType.OrbitCollector: + case EControlPanelEntryType.LocalStation: + if (entity.stationId == 0) return; + if (isInit) + { + LCPObjectEntryEntityInfo.Instance.Set(packet.Index, entity.protoId, entity.stationId, factory.ReadExtraInfoOnEntity(objId)); + conn.SendPacket(LCPObjectEntryEntityInfo.Instance); + } + var station = factory.transport.stationPool[entity.stationId]; + LCPStationEntryUpdate.Instance.Set(packet.Index, station, factory); + conn.SendPacket(LCPStationEntryUpdate.Instance); + break; + + case EControlPanelEntryType.VeinCollector: + if (entity.stationId == 0) return; + if (isInit) + { + LCPObjectEntryEntityInfo.Instance.Set(packet.Index, entity.protoId, entity.stationId, factory.ReadExtraInfoOnEntity(objId)); + conn.SendPacket(LCPObjectEntryEntityInfo.Instance); + } + var veinCollector = factory.transport.stationPool[entity.stationId]; + LCPAdvancedMinerEntryUpdate.Instance.Set(packet.Index, veinCollector, factory); + conn.SendPacket(LCPAdvancedMinerEntryUpdate.Instance); + break; + + case EControlPanelEntryType.Dispenser: + if (entity.dispenserId == 0) return; + if (isInit) + { + LCPObjectEntryEntityInfo.Instance.Set(packet.Index, entity.protoId, entity.dispenserId, factory.ReadExtraInfoOnEntity(objId)); + conn.SendPacket(LCPObjectEntryEntityInfo.Instance); + } + var dispenser = factory.transport.dispenserPool[entity.dispenserId]; + LCPDispenserEntryUpdate.Instance.Set(packet.Index, dispenser, factory); + conn.SendPacket(LCPDispenserEntryUpdate.Instance); + break; + } + } +} diff --git a/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPStationEntryUpdateProcessor.cs b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPStationEntryUpdateProcessor.cs new file mode 100644 index 000000000..9b53a1f91 --- /dev/null +++ b/NebulaNetwork/PacketProcessors/Logistics/ControlPanel/LCPStationEntryUpdateProcessor.cs @@ -0,0 +1,176 @@ +#region + +using NebulaAPI.Packets; +using NebulaModel.Networking; +using NebulaModel.Packets; +using NebulaModel.Packets.Logistics.ControlPanel; +using UnityEngine; + +#endregion + +namespace NebulaNetwork.PacketProcessors.Logistics.ControlPanel; + +[RegisterPacketProcessor] +public class LCPStationEntryUpdateProcessor : PacketProcessor +{ + static readonly StationStore[] stationStores = new StationStore[5]; + + protected override void ProcessPacket(LCPStationEntryUpdate packet, NebulaConnection conn) + { + if (IsHost) return; + + var objectEntryPool = UIRoot.instance.uiGame.controlPanelWindow.objectEntryPool; + for (var i = 0; i < objectEntryPool.Count; i++) + { + if (objectEntryPool[i] != null && objectEntryPool[i].index == packet.Index) + { + var entry = objectEntryPool[i] as UIControlPanelStationEntry; + UpdateEntry(entry, packet); + return; + } + } + } + + private static void UpdateEntry(UIControlPanelStationEntry entry, LCPStationEntryUpdate packet) + { + if (entry == null) return; + + // Modify from UIControlPanelStationEntry._OnUpdate + // Update item UI + for (var i = 0; i < 5; i++) + { + ref var store = ref stationStores[i]; + store.itemId = packet.ItemId[i]; + store.count = packet.ItemCount[i]; + store.localOrder = packet.LocalOrder[i]; + store.remoteOrder = packet.RemoteOrder[i]; + store.max = packet.StoreMax[i]; + store.localLogic = (ELogisticStorage)packet.LocalLogic[i]; + store.remoteLogic = (ELogisticStorage)packet.RemoteLogic[i]; + } + var tmp = entry.station.storage; + entry.station.storage = stationStores; + // expand entry.UpdateItems() + entry.storageItem0.SetVisible(stationStores[0].itemId > 0); + entry.storageItem0._Update(); + entry.storageItem1.SetVisible(stationStores[1].itemId > 0); + entry.storageItem1._Update(); + entry.storageItem2.SetVisible(stationStores[2].itemId > 0); + entry.storageItem2._Update(); + entry.storageItem3.SetVisible(stationStores[3].itemId > 0); + entry.storageItem3._Update(); + entry.storageItem4.SetVisible(stationStores[4].itemId > 0); + entry.storageItem4._Update(); + entry.station.storage = tmp; + + // Update drone and ship count UI + switch (entry.target.entryType) + { + case EControlPanelEntryType.InterstellarStation: + entry.SetDeliveryVisible(true); + entry.droneCountSB.Append(packet.IdleDroneCount); + entry.droneCountSB.Append('/'); + entry.droneCountSB.Append(packet.IdleDroneCount + packet.WorkDroneCount); + entry.droneCountText.text = entry.droneCountSB.ToString(); + entry.droneCountSB.Clear(); + entry.shipCountSB.Append(packet.IdleShipCount); + entry.shipCountSB.Append('/'); + entry.shipCountSB.Append(packet.IdleShipCount + packet.WorkShipCount); + entry.shipCountText.text = entry.shipCountSB.ToString(); + entry.shipCountSB.Clear(); + entry.warperCountText.text = packet.WarperCount.ToString(); + entry.fillNecessaryButton.button.interactable = true; + entry.fillNecessaryImage.raycastTarget = true; + break; + + case EControlPanelEntryType.OrbitCollector: + entry.SetDeliveryVisible(false); + entry.droneCountText.text = ""; + entry.shipCountText.text = ""; + entry.warperCountText.text = ""; + entry.fillNecessaryButton.button.interactable = false; + entry.fillNecessaryImage.raycastTarget = false; + break; + + case EControlPanelEntryType.VeinCollector: + entry.SetDeliveryVisible(false); + entry.droneIconImage.raycastTarget = true; + entry.droneIconImage.color = entry.masterWindow.deliveryIconColor; + entry.droneCountText.color = entry.masterWindow.deliveryTextColor; + entry.droneCountSB.Append(packet.IdleDroneCount); + entry.droneCountSB.Append('/'); + entry.droneCountSB.Append(packet.IdleDroneCount + packet.WorkDroneCount); + entry.droneCountText.text = entry.droneCountSB.ToString(); + entry.droneCountSB.Clear(); + entry.shipCountText.text = ""; + entry.warperCountText.text = ""; + entry.fillNecessaryButton.button.interactable = true; + entry.fillNecessaryImage.raycastTarget = true; + break; + + case EControlPanelEntryType.LocalStation: + entry.SetDeliveryVisible(false); + entry.droneCountText.text = ""; + entry.shipCountText.text = ""; + entry.warperCountText.text = ""; + entry.fillNecessaryButton.button.interactable = false; + entry.fillNecessaryImage.raycastTarget = false; + break; + } + + // Update power UI + entry.powerGroupGo.SetActive(entry.target.entryType != EControlPanelEntryType.OrbitCollector); + var consumerRatio = (float)packet.ConsumerRatio; + int powerStatusCode; + if (consumerRatio >= 1f) + { + entry.powerCircleFg.fillAmount = 1f; + powerStatusCode = 1; + } + else + { + entry.powerCircleFg.fillAmount = consumerRatio; + powerStatusCode = ((consumerRatio >= 0.1f) ? 2 : 3); + } + StringBuilderUtility.WriteKMG1000(entry.sbw, 8, packet.RequirePower, true); + StringBuilderUtility.WriteKMG1000(entry.sbw2, 8, packet.WorkEnergyPerTick * 60L, true); + entry.powerText.text = entry.sbw.ToString(); + entry.maxChargePowerValue.text = entry.sbw2.ToString(); + entry.powerRoundFg.fillAmount = packet.PowerRound; + switch (powerStatusCode) + { + case 1: + entry.powerSignImage.color = entry.masterWindow.powerSignColor1; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor1; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor1; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor1; + entry.powerText.color = entry.masterWindow.powerTextColor1; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor1; + break; + case 2: + entry.powerSignImage.color = entry.masterWindow.powerSignColor2; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor2; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor2; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor2; + entry.powerText.color = entry.masterWindow.powerTextColor2; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor2; + break; + case 3: + entry.powerSignImage.color = entry.masterWindow.powerSignColor3; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor3; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor3; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor3; + entry.powerText.color = entry.masterWindow.powerTextColor3; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor3; + break; + default: + entry.powerSignImage.color = entry.masterWindow.powerSignColor0; + entry.powerCircleBg.color = entry.masterWindow.powerCircleBgColor0; + entry.powerCircleFg.color = entry.masterWindow.powerCircleFgColor0; + entry.powerRoundFg.color = entry.masterWindow.powerRoundFgColor0; + entry.powerText.color = entry.masterWindow.powerTextColor0; + entry.maxChargePowerValue.color = entry.masterWindow.powerTextColor0; + break; + } + } +} diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelAdvancedMinerEntry_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelAdvancedMinerEntry_Patch.cs index f5931a3f2..467b58afa 100644 --- a/NebulaPatcher/Patches/Dynamic/UIControlPanelAdvancedMinerEntry_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelAdvancedMinerEntry_Patch.cs @@ -1,7 +1,10 @@ #region using HarmonyLib; +using NebulaModel.Packets.Logistics; +using NebulaModel.Packets.Logistics.ControlPanel; using NebulaWorld; +using UnityEngine; #endregion @@ -10,13 +13,115 @@ namespace NebulaPatcher.Patches.Dynamic; [HarmonyPatch(typeof(UIControlPanelAdvancedMinerEntry))] internal class UIControlPanelAdvancedMinerEntry_Patch { + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelAdvancedMinerEntry.OnSetTarget))] + public static bool OnSetTarget_Prefix(UIControlPanelAdvancedMinerEntry __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.IsServer) return true; + var factory = GameMain.data.galaxy.PlanetById(__instance.target.astroId).factory; + if (factory == null) + { + LCPObjectEntryRequest.Instance.Set(__instance, true); + Multiplayer.Session.Client.SendPacket(LCPObjectEntryRequest.Instance); + __instance.station = Multiplayer.Session.StationsUI.DummyStationStoreContainer; + __instance.storageItem.station = __instance.station; + __instance.storageItem.SetVisible(false); + return false; + } + return true; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelAdvancedMinerEntry._OnUpdate))] + public static bool Update_Prefix(UIControlPanelAdvancedMinerEntry __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.IsServer) return true; + if (__instance.factory != null) return true; + + UIControlPanelObjectEntry_Patch.OnUpdate(__instance); + __instance.viewToTargetButton.button.interactable = __instance.isLocal; + if (UIControlPanelWindow_Patch.UpdateTimer % 60 == 0) + { + // Request content update every 1s + LCPObjectEntryRequest.Instance.Set(__instance, false); + Multiplayer.Session.Client.SendPacket(LCPObjectEntryRequest.Instance); + } + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelAdvancedMinerEntry.isLocal), MethodType.Getter)] + public static bool IsLocal_Prefix(UIControlPanelAdvancedMinerEntry __instance, ref bool __result) + { + if (__instance.factory == null) + { + __result = false; + return false; + } + return true; + } + [HarmonyPrefix] [HarmonyPatch(nameof(UIControlPanelAdvancedMinerEntry.OnFillNecessaryButtonClick))] - public static bool OnFillNecessaryButtonClick_Prefix() + public static bool OnFillNecessaryButtonClick_Prefix(UIControlPanelAdvancedMinerEntry __instance) { if (!Multiplayer.IsActive) return true; + if (__instance.factory == null || __instance.station == null) + { + UIRealtimeTip.Popup("Unavailable".Translate()); + return false; + } + + var packet = new StationUI() + { + PlanetId = __instance.factory.planetId, + StationId = __instance.station.id, + StationGId = __instance.station.gid + }; + var text = ""; + if (__instance.station.isStellar) + { + int shortAge, previousCount; + + previousCount = __instance.station.idleDroneCount; + shortAge = __instance.station.workDroneDatas.Length - (__instance.station.idleDroneCount + __instance.station.workDroneCount); + UIControlPanelObjectEntry.ReplenishItems(5001, shortAge, ref __instance.station.idleDroneCount, ref text); + packet.SettingIndex = StationUI.EUISettings.SetDroneCount; + packet.SettingValue = (__instance.station.idleDroneCount + __instance.station.workDroneCount); + Multiplayer.Session.Network.SendPacket(packet); + if (Multiplayer.Session.IsClient) __instance.station.idleDroneCount = previousCount; // Wait for server to authorize + + previousCount = __instance.station.idleShipCount; + shortAge = __instance.station.workShipDatas.Length - (__instance.station.idleShipCount + __instance.station.workShipCount); + UIControlPanelObjectEntry.ReplenishItems(5002, shortAge, ref __instance.station.idleShipCount, ref text); + packet.SettingIndex = StationUI.EUISettings.SetShipCount; + packet.SettingValue = (__instance.station.idleShipCount + __instance.station.workShipCount); + Multiplayer.Session.Network.SendPacket(packet); + if (Multiplayer.Session.IsClient) __instance.station.idleShipCount = previousCount; // Wait for server to authorize - // Temporarily disable fill item button. We will sync in the future + previousCount = __instance.station.warperCount; + shortAge = __instance.station.warperMaxCount - __instance.station.warperCount; + UIControlPanelObjectEntry.ReplenishItems(1210, shortAge, ref __instance.station.warperCount, ref text); + packet.SettingIndex = StationUI.EUISettings.SetWarperCount; + packet.SettingValue = __instance.station.warperCount; + Multiplayer.Session.Network.SendPacket(packet); + if (Multiplayer.Session.IsClient) __instance.station.warperCount = previousCount; // Wait for server to authorize + } + else + { + var previousCount = __instance.station.idleDroneCount; + var shortAge = __instance.station.workDroneDatas.Length - (__instance.station.idleDroneCount + __instance.station.workDroneCount); + UIControlPanelObjectEntry.ReplenishItems(5001, shortAge, ref __instance.station.idleDroneCount, ref text); + packet.SettingIndex = StationUI.EUISettings.SetDroneCount; + packet.SettingValue = (__instance.station.idleDroneCount + __instance.station.workDroneCount); + Multiplayer.Session.Network.SendPacket(packet); + if (Multiplayer.Session.IsClient) __instance.station.idleDroneCount = previousCount; // Wait for server to authorize + } + if (!string.IsNullOrEmpty(text)) + { + UIRealtimeTip.Popup(text, false, 0); + VFAudio.Create("equip-1", GameMain.mainPlayer.transform, Vector3.zero, true, 4, -1, -1L); + } return false; } } diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelDispenserEntry_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelDispenserEntry_Patch.cs index ab272fb0f..d46e302fe 100644 --- a/NebulaPatcher/Patches/Dynamic/UIControlPanelDispenserEntry_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelDispenserEntry_Patch.cs @@ -1,7 +1,10 @@ #region using HarmonyLib; +using NebulaModel.Packets.Logistics; +using NebulaModel.Packets.Logistics.ControlPanel; using NebulaWorld; +using UnityEngine; #endregion @@ -10,13 +13,78 @@ namespace NebulaPatcher.Patches.Dynamic; [HarmonyPatch(typeof(UIControlPanelDispenserEntry))] internal class UIControlPanelDispenserEntry_Patch { + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelDispenserEntry.OnSetTarget))] + public static bool OnSetTarget_Prefix(UIControlPanelDispenserEntry __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.IsServer) return true; + var planet = GameMain.data.galaxy.PlanetById(__instance.target.astroId); + var factory = planet.factory; + if (factory == null) + { + LCPObjectEntryRequest.Instance.Set(__instance, true); + Multiplayer.Session.Client.SendPacket(LCPObjectEntryRequest.Instance); + return false; + } + return true; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelDispenserEntry._OnUpdate))] + public static bool Update_Prefix(UIControlPanelDispenserEntry __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.IsServer) return true; + if (__instance.factory != null) return true; + + UIControlPanelObjectEntry_Patch.OnUpdate(__instance); + __instance.viewToTargetButton.button.interactable = __instance.isLocal; + if (UIControlPanelWindow_Patch.UpdateTimer % 60 == 0) + { + // Request content update every 1s + LCPObjectEntryRequest.Instance.Set(__instance, false); + Multiplayer.Session.Client.SendPacket(LCPObjectEntryRequest.Instance); + } + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelDispenserEntry.isLocal), MethodType.Getter)] + public static bool IsLocal_Prefix(UIControlPanelDispenserEntry __instance, ref bool __result) + { + if (__instance.factory == null) + { + __result = false; + return false; + } + return true; + } + + [HarmonyPrefix] [HarmonyPatch(nameof(UIControlPanelDispenserEntry.OnFillNecessaryButtonClick))] public static bool OnFillNecessaryButtonClick_Prefix(UIControlPanelDispenserEntry __instance) { if (!Multiplayer.IsActive) return true; + if (__instance.factory == null || __instance.dispenser == null) + { + UIRealtimeTip.Popup("Unavailable".Translate()); + return false; + } + + var text = ""; + var num = __instance.dispenser.workCourierDatas.Length - (__instance.dispenser.idleCourierCount + __instance.dispenser.workCourierCount); + UIControlPanelObjectEntry.ReplenishItems(5001, num, ref __instance.dispenser.idleCourierCount, ref text); + if (!string.IsNullOrEmpty(text)) + { + UIRealtimeTip.Popup(text, false, 0); + VFAudio.Create("equip-1", GameMain.mainPlayer.transform, Vector3.zero, true, 4, -1, -1L); + } + Multiplayer.Session.Network.SendPacketToLocalStar( + new DispenserSettingPacket(__instance.factory.planetId, + __instance.id, + EDispenserSettingEvent.SetCourierCount, + __instance.dispenser.workCourierCount + __instance.dispenser.idleCourierCount)); - // Temporarily disable fill item button. We will sync in the future return false; } } diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelObjectEntry_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelObjectEntry_Patch.cs new file mode 100644 index 000000000..8dd621217 --- /dev/null +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelObjectEntry_Patch.cs @@ -0,0 +1,28 @@ +#region + +using System.Collections.Generic; +using HarmonyLib; + +#endregion + +namespace NebulaPatcher.Patches.Dynamic; +#pragma warning disable IDE0060 // Remove unused parameter + +[HarmonyPatch(typeof(UIControlPanelObjectEntry))] +internal class UIControlPanelObjectEntry_Patch +{ + [HarmonyReversePatch(HarmonyReversePatchType.Original)] + [HarmonyPatch(nameof(UIControlPanelObjectEntry._OnUpdate))] + public static void OnUpdate(UIControlPanelObjectEntry entry) + { + // Use HarmonyReversePatch to call base._OnUpdate as base is not available in static function + _ = Transpiler(null); + return; + + static IEnumerable Transpiler(IEnumerable instructions) + { + return instructions; + } + } +} + diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelPlanetEntry_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelPlanetEntry_Patch.cs new file mode 100644 index 000000000..ea9a2404d --- /dev/null +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelPlanetEntry_Patch.cs @@ -0,0 +1,52 @@ +#region + +using HarmonyLib; +using NebulaWorld; +using UITools; + +#endregion + +namespace NebulaPatcher.Patches.Dynamic; + +[HarmonyPatch(typeof(UIControlPanelPlanetEntry))] +internal class UIControlPanelPlanetEntry_Patch +{ + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelPlanetEntry.UpdateBanner))] + public static bool UpdateBanner_Prefix(UIControlPanelPlanetEntry __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.IsServer) return true; + + // Copy from vanilla code, except that ref to planet.factory is removed + if (!__instance.isTargetDataValid) + { + return false; + } + if (__instance.isLocal) + { + __instance.distanceText.text = "当前星球".Translate(); + __instance.distanceText.font = __instance.masterWindow.FONT_SAIRASB; + } + else + { + var uPosition = __instance.planet.uPosition; + var magnitude = (GameMain.mainPlayer.uPosition - uPosition).magnitude; // No need to access planet.factory in vanilla code + var distanceLY = magnitude / 2400000.0; + if (distanceLY < 0.10000000149011612) + { + var distanceAU = magnitude / 40000.0; + __instance.distanceText.text = string.Format("距伊卡洛斯距离提示".Translate(), distanceAU.ToString("F1") + " AU"); + } + else + { + __instance.distanceText.text = string.Format("距伊卡洛斯距离提示".Translate(), distanceLY.ToString("F1") + " ly"); + } + __instance.distanceText.font = __instance.masterWindow.FONT_DIN; + } + __instance.planetTypeText.text = __instance.planet.typeString; + var displayName = __instance.planet.displayName; + Utils.UITextTruncateShow(__instance.planetNameText, displayName, __instance.planetNameTextWidthLimit, ref __instance.planetNameTextSettings); + + return false; + } +} diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelStationEntry_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelStationEntry_Patch.cs index 64d7ee990..7c159913d 100644 --- a/NebulaPatcher/Patches/Dynamic/UIControlPanelStationEntry_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelStationEntry_Patch.cs @@ -1,7 +1,10 @@ #region using HarmonyLib; +using NebulaModel.Packets.Logistics; +using NebulaModel.Packets.Logistics.ControlPanel; using NebulaWorld; +using UnityEngine; #endregion @@ -10,13 +13,123 @@ namespace NebulaPatcher.Patches.Dynamic; [HarmonyPatch(typeof(UIControlPanelStationEntry))] internal class UIControlPanelStationEntry_Patch { + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationEntry.OnSetTarget))] + public static bool OnSetTarget_Prefix(UIControlPanelStationEntry __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.IsServer) return true; + var factory = GameMain.data.galaxy.PlanetById(__instance.target.astroId).factory; + if (factory == null) + { + LCPObjectEntryRequest.Instance.Set(__instance, true); + Multiplayer.Session.Client.SendPacket(LCPObjectEntryRequest.Instance); + __instance.station = Multiplayer.Session.StationsUI.DummyStationStoreContainer; + __instance.storageItem0.station = __instance.station; + __instance.storageItem1.station = __instance.station; + __instance.storageItem2.station = __instance.station; + __instance.storageItem3.station = __instance.station; + __instance.storageItem4.station = __instance.station; + __instance.storageItem0.SetVisible(false); + __instance.storageItem1.SetVisible(false); + __instance.storageItem2.SetVisible(false); + __instance.storageItem3.SetVisible(false); + __instance.storageItem4.SetVisible(false); + return false; + } + return true; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationEntry._OnUpdate))] + public static bool Update_Prefix(UIControlPanelStationEntry __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.IsServer) return true; + if (__instance.factory != null) return true; + + UIControlPanelObjectEntry_Patch.OnUpdate(__instance); + __instance.viewToTargetButton.button.interactable = __instance.isLocal; + if (UIControlPanelWindow_Patch.UpdateTimer % 60 == 0) + { + // Request content update every 1s + LCPObjectEntryRequest.Instance.Set(__instance, false); + Multiplayer.Session.Client.SendPacket(LCPObjectEntryRequest.Instance); + } + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelStationEntry.isLocal), MethodType.Getter)] + public static bool IsLocal_Prefix(UIControlPanelAdvancedMinerEntry __instance, ref bool __result) + { + if (__instance.factory == null) + { + __result = false; + return false; + } + return true; + } + [HarmonyPrefix] [HarmonyPatch(nameof(UIControlPanelStationEntry.OnFillNecessaryButtonClick))] - public static bool OnFillNecessaryButtonClick_Prefix() + public static bool OnFillNecessaryButtonClick_Prefix(UIControlPanelStationEntry __instance) { if (!Multiplayer.IsActive) return true; + if (__instance.factory == null || __instance.station == null) + { + UIRealtimeTip.Popup("Unavailable".Translate()); + return false; + } + + var packet = new StationUI() + { + PlanetId = __instance.factory.planetId, + StationId = __instance.station.id, + StationGId = __instance.station.gid + }; + var text = ""; + if (__instance.station.isStellar) + { + int shortAge, previousCount; + + previousCount = __instance.station.idleDroneCount; + shortAge = __instance.station.workDroneDatas.Length - (__instance.station.idleDroneCount + __instance.station.workDroneCount); + UIControlPanelObjectEntry.ReplenishItems(5001, shortAge, ref __instance.station.idleDroneCount, ref text); + packet.SettingIndex = StationUI.EUISettings.SetDroneCount; + packet.SettingValue = (__instance.station.idleDroneCount + __instance.station.workDroneCount); + Multiplayer.Session.Network.SendPacket(packet); + if (Multiplayer.Session.IsClient) __instance.station.idleDroneCount = previousCount; // Wait for server to authorize + + previousCount = __instance.station.idleShipCount; + shortAge = __instance.station.workShipDatas.Length - (__instance.station.idleShipCount + __instance.station.workShipCount); + UIControlPanelObjectEntry.ReplenishItems(5002, shortAge, ref __instance.station.idleShipCount, ref text); + packet.SettingIndex = StationUI.EUISettings.SetShipCount; + packet.SettingValue = (__instance.station.idleShipCount + __instance.station.workShipCount); + Multiplayer.Session.Network.SendPacket(packet); + if (Multiplayer.Session.IsClient) __instance.station.idleShipCount = previousCount; // Wait for server to authorize - // Temporarily disable fill item button. We will sync in the future + previousCount = __instance.station.warperCount; + shortAge = __instance.station.warperMaxCount - __instance.station.warperCount; + UIControlPanelObjectEntry.ReplenishItems(1210, shortAge, ref __instance.station.warperCount, ref text); + packet.SettingIndex = StationUI.EUISettings.SetWarperCount; + packet.SettingValue = __instance.station.warperCount; + Multiplayer.Session.Network.SendPacket(packet); + if (Multiplayer.Session.IsClient) __instance.station.warperCount = previousCount; // Wait for server to authorize + } + else + { + var previousCount = __instance.station.idleDroneCount; + var shortAge = __instance.station.workDroneDatas.Length - (__instance.station.idleDroneCount + __instance.station.workDroneCount); + UIControlPanelObjectEntry.ReplenishItems(5001, shortAge, ref __instance.station.idleDroneCount, ref text); + packet.SettingIndex = StationUI.EUISettings.SetDroneCount; + packet.SettingValue = (__instance.station.idleDroneCount + __instance.station.workDroneCount); + Multiplayer.Session.Network.SendPacket(packet); + if (Multiplayer.Session.IsClient) __instance.station.idleDroneCount = previousCount; // Wait for server to authorize + } + if (!string.IsNullOrEmpty(text)) + { + UIRealtimeTip.Popup(text, false, 0); + VFAudio.Create("equip-1", GameMain.mainPlayer.transform, Vector3.zero, true, 4, -1, -1L); + } return false; } } diff --git a/NebulaPatcher/Patches/Dynamic/UIControlPanelWindow_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIControlPanelWindow_Patch.cs new file mode 100644 index 000000000..927917a1f --- /dev/null +++ b/NebulaPatcher/Patches/Dynamic/UIControlPanelWindow_Patch.cs @@ -0,0 +1,78 @@ +#region + +using HarmonyLib; +using NebulaModel.Packets.Logistics.ControlPanel; +using NebulaWorld; + +#endregion + +namespace NebulaPatcher.Patches.Dynamic; + +[HarmonyPatch(typeof(UIControlPanelWindow))] +internal class UIControlPanelWindow_Patch +{ + public static int UpdateTimer { get; private set; } + + [HarmonyPrefix, HarmonyPriority(Priority.Last)] + [HarmonyPatch(nameof(UIControlPanelWindow.DetermineFilterResults))] + public static bool DetermineFilterResults_Prefix(UIControlPanelWindow __instance) + { + if (!Multiplayer.IsActive || Multiplayer.Session.IsServer) return true; + + // Send request to server and wait for response + __instance.needDetermineFilterResults = false; + Multiplayer.Session.Client.SendPacket(new LCPFilterResultsRequest(__instance.filter)); + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(UIControlPanelWindow.DetermineSelectionInspector))] + public static bool DetermineSelectionInspectorPrefix(UIControlPanelWindow __instance) + { + 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) + { + UIRoot.instance.uiGame.OpenStationWindow(); + } + break; + + case EControlPanelEntryType.Dispenser: + // Close station 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; + if (UIRoot.instance.uiGame.inspectDispenserId == 0 && dispenserId > 0) + { + UIRoot.instance.uiGame.OpenDispenserWindow(); + } + break; + } + return false; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(UIControlPanelWindow._OnUpdate))] + public static void OnUpdate_Postfix() + { + UpdateTimer = (++UpdateTimer) % 600; + } +} diff --git a/NebulaWorld/Logistics/StationUIManager.cs b/NebulaWorld/Logistics/StationUIManager.cs index 2e39a104a..fd3f629d3 100644 --- a/NebulaWorld/Logistics/StationUIManager.cs +++ b/NebulaWorld/Logistics/StationUIManager.cs @@ -27,8 +27,19 @@ public int StorageMaxChangeId public ToggleSwitch IsIncomingRequest { get; set; } = new(); + public StationComponent DummyStationStoreContainer { get; private set; } // For UIControlPanelStorageItem + + public StationUIManager() + { + DummyStationStoreContainer = new() + { + storage = new StationStore[5] + }; + } + public void Dispose() { + DummyStationStoreContainer = null; GC.SuppressFinalize(this); } @@ -162,7 +173,7 @@ private static void UpdateSettingsUI(StationComponent stationComponent, ref Stat } case StationUI.EUISettings.MaxTripVessel: { - double value = packet.SettingValue; + var value = packet.SettingValue; value = value switch { > 40.5 => 10000.0, @@ -186,7 +197,7 @@ private static void UpdateSettingsUI(StationComponent stationComponent, ref Stat } case StationUI.EUISettings.WarpDistance: { - double value = packet.SettingValue; + var value = packet.SettingValue; switch (value) { case < 1.5: