feat(economy): add Bestellsystem mit Lieferzeit
- SupplierService: Bestellungen mit Lieferzeit-Berechnung - OrderTerminal: Spieler-Interaktion zum Aufgeben von Bestellungen - StorageCrateRegistry + StorageCrate.Restock: Server registriert Kisten und füllt sie bei Lieferung wieder auf - GameClock.TotalHours: durchgehende Spielzeit für Lieferzeit-Berechnung - ROADMAP: Bestellsystem-Punkt als erledigt markiert Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
using AfterHours.Data;
|
||||
using AfterHours.Economy;
|
||||
using AfterHours.Interaction;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AfterHours.Shop
|
||||
{
|
||||
/// <summary>
|
||||
/// Backroom-Terminal zum Nachbestellen eines festen Produkts beim
|
||||
/// Großhandel. Produkt/Menge sind pro Instanz im Inspector konfiguriert.
|
||||
/// </summary>
|
||||
public sealed class OrderTerminal : NetworkBehaviour, IInteractable
|
||||
{
|
||||
[SerializeField] private ProductCatalog _catalog;
|
||||
[SerializeField] private int _productId = -1;
|
||||
[SerializeField] private int _orderQuantity = 50;
|
||||
|
||||
public string GetPrompt(ulong clientId)
|
||||
{
|
||||
var product = _catalog.Get(_productId);
|
||||
string name = product != null ? product.DisplayName : "?";
|
||||
float cost = product != null ? product.WholesalePrice * _orderQuantity : 0f;
|
||||
return $"{name} nachbestellen ({_orderQuantity} Stk. — {cost:0.00} €)";
|
||||
}
|
||||
|
||||
/// <summary>Server: löst eine Bestellung beim SupplierService aus.</summary>
|
||||
public void Interact(NetworkObject actor)
|
||||
{
|
||||
if (!IsServer) return;
|
||||
SupplierService.Instance?.PlaceOrder(_productId, _orderQuantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 045aa93f3792d4847ab62d54134471e5
|
||||
@@ -25,7 +25,15 @@ namespace AfterHours.Shop
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (IsServer) _quantity.Value = _startingQuantity;
|
||||
if (!IsServer) return;
|
||||
|
||||
_quantity.Value = _startingQuantity;
|
||||
StorageCrateRegistry.Instance.Register(this);
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
if (IsServer) StorageCrateRegistry.Instance.Unregister(this);
|
||||
}
|
||||
|
||||
public string GetPrompt(ulong clientId)
|
||||
@@ -45,5 +53,12 @@ namespace AfterHours.Shop
|
||||
int taken = hands.TryTake(_productId, want);
|
||||
_quantity.Value -= taken;
|
||||
}
|
||||
|
||||
/// <summary>Server: Lieferung trifft ein.</summary>
|
||||
public void Restock(int quantity)
|
||||
{
|
||||
if (!IsServer || quantity <= 0) return;
|
||||
_quantity.Value += quantity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AfterHours.Shop
|
||||
{
|
||||
/// <summary>
|
||||
/// Serverseitige Liste aller aktiven Lagerkisten, damit der SupplierService
|
||||
/// eine Lieferung der richtigen Kiste zuordnen kann.
|
||||
/// </summary>
|
||||
public sealed class StorageCrateRegistry
|
||||
{
|
||||
public static readonly StorageCrateRegistry Instance = new();
|
||||
|
||||
private readonly List<StorageCrate> _crates = new();
|
||||
|
||||
public void Register(StorageCrate crate) => _crates.Add(crate);
|
||||
|
||||
public void Unregister(StorageCrate crate) => _crates.Remove(crate);
|
||||
|
||||
/// <summary>Erste Kiste, die dieses Produkt führt.</summary>
|
||||
public StorageCrate FindFor(int productId)
|
||||
{
|
||||
foreach (var crate in _crates)
|
||||
if (crate != null && crate.ProductId == productId)
|
||||
return crate;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d67201bcc28c49428bc6c0ead7f1ff7
|
||||
Reference in New Issue
Block a user