110 lines
6.1 KiB
C#
110 lines
6.1 KiB
C#
using System.Collections.Generic;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
|
||
namespace DepthsOfGreed.HandbookUI
|
||
{
|
||
public sealed partial class SupplyBasementController
|
||
{
|
||
[Header("Versorgungssystem – optional")]
|
||
[Tooltip("MonoBehaviour mit ISupplyGameplay. Leer = bisherige Bedien- und Fahrvorschau.")]
|
||
[SerializeField] private MonoBehaviour supplyBackend;
|
||
public TMP_Text[] storageAmounts, bufferAmounts, magazineAmounts;
|
||
public bool HasSupplyBackend => supplyBackend && supplyBackend is ISupplyGameplay;
|
||
public ISupplyGameplay SupplyBackend => HasSupplyBackend ? (ISupplyGameplay)supplyBackend : null;
|
||
private SupplyState supplyState;
|
||
private float commandMessageUntil;
|
||
private readonly List<BuiltObjectSnapshot> supplyObjects = new List<BuiltObjectSnapshot>();
|
||
|
||
public void BindSupplyBackend(MonoBehaviour backend)
|
||
{
|
||
if (backend && !(backend is ISupplyGameplay))
|
||
{ Debug.LogError("Versorgung: Komponente muss ISupplyGameplay implementieren.", backend); return; }
|
||
supplyBackend = backend;
|
||
// Filled on the next UI refresh; safe even before Awake.
|
||
nextRefresh = 0;
|
||
}
|
||
private IReadOnlyList<BuiltObjectSnapshot> GetSupplyObjects()
|
||
{
|
||
if (!HasSupplyBackend)
|
||
return placement && placement.Backend != null ? placement.Backend.BuiltObjects : null;
|
||
supplyState = SupplyBackend.ReadState();
|
||
supplyObjects.Clear();
|
||
if (supplyState?.towers != null)
|
||
foreach (var t in supplyState.towers)
|
||
if (t != null && t.type) supplyObjects.Add(new BuiltObjectSnapshot { instanceId = t.instanceId, type = t.type });
|
||
Priority = supplyState == null ? -1 : (int)supplyState.priority;
|
||
RenderPriority(); RenderAmounts();
|
||
return supplyObjects;
|
||
}
|
||
private TowerSupplyState FindTower(long id)
|
||
{
|
||
if (supplyState?.towers != null) foreach (var t in supplyState.towers) if (t != null && t.instanceId == id) return t;
|
||
return null;
|
||
}
|
||
private bool TrySetBackendConnection(long id, bool connected)
|
||
{
|
||
if (!HasSupplyBackend) return false;
|
||
var result = SupplyBackend.SetConnected(id, connected);
|
||
if (result.accepted) ConnectionChanged?.Invoke(id, connected);
|
||
else ShowCommandMessage(result.message);
|
||
RefreshConnections(); return true;
|
||
}
|
||
private bool TrySetBackendPriority(int kind)
|
||
{
|
||
if (!HasSupplyBackend) return false;
|
||
int desired = Priority == kind ? -1 : kind;
|
||
var result = SupplyBackend.SetPriority((SupplyKind)desired);
|
||
if (result.accepted) PriorityChanged?.Invoke(desired);
|
||
else ShowCommandMessage(result.message);
|
||
RefreshConnections(); return true;
|
||
}
|
||
private void ShowCommandMessage(string message)
|
||
{ truckStatus.text = string.IsNullOrWhiteSpace(message) ? "Aktion derzeit nicht möglich" : message; commandMessageUntil = Time.unscaledTime + 2; }
|
||
private void RenderPriority()
|
||
{
|
||
for (int i = 0; i < priorityButtons.Length; i++)
|
||
{
|
||
priorityButtons[i].GetComponent<UnityEngine.UI.Image>().color = Priority == i ? ColorFor(i) : new Color(.72f,.72f,.72f);
|
||
priorityLabels[i].text = Priority == i ? "Vorrang aktiv" : "Vorrang geben";
|
||
}
|
||
}
|
||
private static string Amount(float value, float capacity)
|
||
=> Mathf.Max(0,value).ToString("0.#") + " / " + Mathf.Max(0,capacity).ToString("0.#");
|
||
private void RenderAmounts()
|
||
{
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
SupplyChannelState channel = null;
|
||
if (supplyState?.channels != null) foreach (var item in supplyState.channels) if (item != null && (int)item.kind == i) { channel = item; break; }
|
||
if (storageAmounts != null && i < storageAmounts.Length && storageAmounts[i]) storageAmounts[i].text = channel == null ? "— / —" : Amount(channel.storage, channel.storageCapacity);
|
||
if (bufferAmounts != null && i < bufferAmounts.Length && bufferAmounts[i]) bufferAmounts[i].text = channel == null ? "Vorrat: —" : Amount(channel.buffer, channel.bufferCapacity);
|
||
}
|
||
}
|
||
private void RenderMagazine(int slot, long id)
|
||
{
|
||
if (magazineAmounts == null || slot >= magazineAmounts.Length || !magazineAmounts[slot]) return;
|
||
var state = HasSupplyBackend ? FindTower(id) : null;
|
||
magazineAmounts[slot].gameObject.SetActive(state != null);
|
||
if (state != null) magazineAmounts[slot].text = "Magazin: " + Amount(state.magazine, state.magazineCapacity);
|
||
}
|
||
private float StopX(SupplyStop stop) => stop == SupplyStop.Distributor ? unloadingPosition : loadingPositions[Mathf.Clamp((int)stop,0,2)];
|
||
private void RenderBackendTruck()
|
||
{
|
||
var state = supplyState?.truck;
|
||
if (state == null) { if(Time.unscaledTime >= commandMessageUntil)truckStatus.text = "LKW bereit"; return; }
|
||
var p = truck.anchoredPosition;
|
||
p.x = state.phase == SupplyTruckPhase.Driving
|
||
? Mathf.Lerp(StopX(state.from), StopX(state.to), Mathf.Clamp01(state.progress)) : StopX(state.to);
|
||
truck.anchoredPosition = p;
|
||
float direction = StopX(state.to) - StopX(state.from);
|
||
if (state.phase == SupplyTruckPhase.Driving && Mathf.Abs(direction) > .1f)
|
||
truck.localScale = new Vector3(Mathf.Abs(truckScale.x)*Mathf.Sign(direction),truckScale.y,truckScale.z);
|
||
if(Time.unscaledTime < commandMessageUntil)return;
|
||
string phase = state.phase == SupplyTruckPhase.Loading ? "Beladen" : state.phase == SupplyTruckPhase.Unloading ? "Abladen" : state.phase == SupplyTruckPhase.Driving ? "Unterwegs" : "Bereit";
|
||
int kind = (int)state.cargoKind;
|
||
truckStatus.text = phase + (kind >= 0 && kind < kinds.Length ? " · " + kinds[kind] + " " + Amount(state.cargo,state.cargoCapacity) : "");
|
||
}
|
||
}
|
||
}
|