Implement Cargo Console (#413)

* Implement Cargo Console

Add to CargoConsoleComponent GalacticBank information for syncing Bank Account Balance.

Implement CargoOrderDatabase on the server side and a list of orders in the CargoOrderDatabaseComponent on the client side. This makes it easier to change data on the server side but also utilize the state syncing between components.

Implement GalacticMarketComponent.
Only productIds get sent. Both client and server create their lists from YAML.

Implement basic spawning of items from approved orders in CargoOrderDatabase.

* Finish Cargo Console

Add validation to make sure Order Amount is one or more.

Implement approve and cancel buttons to CargoConsoleMenu orders list row.

Add price to CargoConsoleMenu product list row.

Implement CargoOrderDataManager to consolidate CargoOrder lists.

Refactor CargoOrderDatabaseComponent to use CargoOrderDataManager instead of storing duplicate lists.

Implement canceling orders.
Implement approving orders.

Fix sprite links.

Implement Cargo Request Console.
This commit is contained in:
ShadowCommander
2019-11-21 16:37:15 -08:00
committed by Pieter-Jan Briers
parent 58709d2d26
commit 1580750606
29 changed files with 1867 additions and 12 deletions

View File

@@ -0,0 +1,20 @@
using System;
namespace Content.Server.Cargo
{
public class CargoBankAccount : ICargoBankAccount
{
public int Id { get; }
public string Name { get; }
public int Balance { get; set; }
public CargoBankAccount(int id, string name, int balance)
{
Id = id;
Name = name;
Balance = balance;
}
}
}

View File

@@ -0,0 +1,99 @@
using Content.Server.GameObjects.Components.Cargo;
using Content.Shared.Prototypes.Cargo;
using System;
using System.Collections.Generic;
namespace Content.Server.Cargo
{
public class CargoOrderDataManager : ICargoOrderDataManager
{
private readonly Dictionary<int, CargoOrderDatabase> _accounts = new Dictionary<int, CargoOrderDatabase>();
private readonly List<CargoOrderDatabaseComponent> _components = new List<CargoOrderDatabaseComponent>();
public CargoOrderDataManager()
{
CreateAccount(0);
}
public void CreateAccount(int id)
{
_accounts.Add(id, new CargoOrderDatabase(id));
}
public bool TryGetAccount(int id, out CargoOrderDatabase account)
{
if (_accounts.TryGetValue(id, out var _account))
{
account = _account;
return true;
}
account = null;
return false;
}
/// <summary>
/// Adds an order to the database.
/// </summary>
/// <param name="requester">The person who requested the item.</param>
/// <param name="reason">The reason the product was requested.</param>
/// <param name="productId">The ID of the product requested.</param>
/// <param name="amount">The amount of the products requested.</param>
/// <param name="payingAccountId">The ID of the bank account paying for the order.</param>
/// <param name="approved">Whether the order will be bought when the orders are processed.</param>
public virtual void AddOrder(int id, string requester, string reason, string productId, int amount, int payingAccountId)
{
if (amount < 1 || !TryGetAccount(id, out var account))
return;
account.AddOrder(requester, reason, productId, amount, payingAccountId);
SyncComponentsWithId(id);
}
public void RemoveOrder(int id, int orderNumber)
{
if (!TryGetAccount(id, out var account))
return;
account.RemoveOrder(orderNumber);
SyncComponentsWithId(id);
}
public void ApproveOrder(int id, int orderNumber)
{
if (!TryGetAccount(id, out var account))
return;
account.ApproveOrder(orderNumber);
SyncComponentsWithId(id);
}
private void SyncComponentsWithId(int id)
{
foreach (var component in _components)
{
if (!component.ConnectedToDatabase || component.Database.Id != id)
continue;
component.Dirty();
}
}
public List<CargoOrderData> RemoveAndGetApprovedFrom(CargoOrderDatabase database)
{
var approvedOrders = database.SpliceApproved();
SyncComponentsWithId(database.Id);
return approvedOrders;
}
public void AddComponent(CargoOrderDatabaseComponent component)
{
if (_components.Contains(component))
return;
_components.Add(component);
component.Database = _accounts[0];
}
public List<CargoOrderData> GetOrdersFromAccount(int accountId)
{
if (!TryGetAccount(accountId, out var account))
return null;
return account.GetOrders();
}
}
}

View File

@@ -0,0 +1,104 @@
using Content.Shared.Prototypes.Cargo;
using System.Collections.Generic;
using System.Linq;
namespace Content.Server.Cargo
{
public class CargoOrderDatabase
{
private Dictionary<int, CargoOrderData> _orders = new Dictionary<int, CargoOrderData>();
private int _orderNumber = 0;
public CargoOrderDatabase(int id)
{
Id = id;
}
public int Id { get; private set; }
/// <summary>
/// Removes all orders from the database.
/// </summary>
public void Clear()
{
_orders.Clear();
}
/// <summary>
/// Returns a list of all orders.
/// </summary>
/// <returns>A list of orders</returns>
public List<CargoOrderData> GetOrders()
{
return _orders.Values.ToList();
}
public bool TryGetOrder(int id, out CargoOrderData order)
{
if (_orders.TryGetValue(id, out var _order))
{
order = _order;
return true;
}
order = null;
return false;
}
public List<CargoOrderData> SpliceApproved()
{
var orders = _orders.Values.Where(order => order.Approved).ToList();
foreach (var order in orders)
_orders.Remove(order.OrderNumber);
return orders;
}
/// <summary>
/// Adds an order to the database.
/// </summary>
/// <param name="requester">The person who requested the item.</param>
/// <param name="reason">The reason the product was requested.</param>
/// <param name="productId">The ID of the product requested.</param>
/// <param name="amount">The amount of the products requested.</param>
/// <param name="payingAccountId">The ID of the bank account paying for the order.</param>
/// <param name="approved">Whether the order will be bought when the orders are processed.</param>
public void AddOrder(string requester, string reason, string productId, int amount, int payingAccountId)
{
var order = new CargoOrderData(_orderNumber, requester, reason, productId, amount, payingAccountId);
if (Contains(order))
return;
_orders.Add(_orderNumber, order);
_orderNumber += 1;
}
/// <summary>
/// Removes an order from the database.
/// </summary>
/// <param name="order">The order to be removed.</param>
/// <returns>Whether it could be removed or not</returns>
public bool RemoveOrder(int orderNumber)
{
return _orders.Remove(orderNumber);
}
/// <summary>
/// Approves an order in the database.
/// </summary>
/// <param name="order">The order to be approved.</param>
public void ApproveOrder(int orderNumber)
{
if (!_orders.TryGetValue(orderNumber, out var order))
return;
order.Approved = true;
}
/// <summary>
/// Returns whether the database contains the order or not.
/// </summary>
/// <param name="order">The order to check</param>
/// <returns>Whether the database contained the order or not.</returns>
public bool Contains(CargoOrderData order)
{
return _orders.ContainsValue(order);
}
}
}

View File

@@ -0,0 +1,109 @@
using Content.Server.GameObjects.Components.Cargo;
using Robust.Shared.Timing;
using System;
using System.Collections.Generic;
namespace Content.Server.Cargo
{
public class GalacticBankManager : IGalacticBankManager
{
private readonly float DELAY = 10f;
private readonly int POINT_INCREASE = 10;
private int _index = 0;
private float _timer = 10f;
private readonly Dictionary<int, CargoBankAccount> _accounts = new Dictionary<int, CargoBankAccount>();
private readonly List<CargoConsoleComponent> _components = new List<CargoConsoleComponent>();
public GalacticBankManager()
{
CreateBankAccount("Orbital Monitor IV Station", 100000);
}
public IEnumerable<CargoBankAccount> GetAllBankAccounts()
{
return _accounts.Values;
}
public void Shutdown()
{
throw new System.NotImplementedException();
}
public void CreateBankAccount(string name, int balance = 0)
{
var account = new CargoBankAccount(_index, name, balance);
_accounts.Add(_index, account);
_index += 1;
}
public CargoBankAccount GetBankAccount(int id)
{
return _accounts[id];
}
public bool TryGetBankAccount(int id, out CargoBankAccount account)
{
if (_accounts.TryGetValue(id, out var _account))
{
account = _account;
return true;
}
account = null;
return false;
}
public void Update(FrameEventArgs frameEventArgs)
{
_timer += frameEventArgs.DeltaSeconds;
if (_timer < DELAY)
return;
_timer -= DELAY;
foreach (var account in GetAllBankAccounts())
{
account.Balance += POINT_INCREASE;
}
SyncComponents();
}
private void SyncComponents()
{
foreach (var component in _components)
{
var account = GetBankAccount(component.BankId);
if (account == null)
continue;
component.SetState(account.Id, account.Name, account.Balance);
}
}
private void SyncComponentsWithId(int id)
{
var account = GetBankAccount(id);
foreach (var component in _components)
{
if (component.BankId != id)
continue;
component.SetState(account.Id, account.Name, account.Balance);
}
}
public void AddComponent(CargoConsoleComponent component)
{
if (_components.Contains(component))
return;
_components.Add(component);
}
public bool ChangeBalance(int id, int n)
{
if (!TryGetBankAccount(id, out var account))
return false;
if (account.Balance + n < 0)
return false;
account.Balance += n;
SyncComponentsWithId(account.Id);
return true;
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace Content.Server.Cargo
{
public interface ICargoBankAccount
{
int Id { get; }
string Name { get; }
int Balance { get; }
}
}

View File

@@ -0,0 +1,17 @@
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Cargo;
using Content.Shared.Prototypes.Cargo;
namespace Content.Server.Cargo
{
public interface ICargoOrderDataManager
{
bool TryGetAccount(int id, out CargoOrderDatabase account);
void AddOrder(int id, string requester, string reason, string productId, int amount, int payingAccountId);
void RemoveOrder(int id, int orderNumber);
void ApproveOrder(int id, int orderNumber);
void AddComponent(CargoOrderDatabaseComponent component);
List<CargoOrderData> GetOrdersFromAccount(int accountId);
List<CargoOrderData> RemoveAndGetApprovedFrom(CargoOrderDatabase database);
}
}

View File

@@ -0,0 +1,20 @@
using Content.Server.GameObjects.Components.Cargo;
using Robust.Shared.Timing;
using System.Collections.Generic;
namespace Content.Server.Cargo
{
public interface IGalacticBankManager
{
IEnumerable<CargoBankAccount> GetAllBankAccounts();
void Shutdown();
void Update(FrameEventArgs frameEventArgs);
void CreateBankAccount(string name, int balance);
CargoBankAccount GetBankAccount(int id);
void AddComponent(CargoConsoleComponent cargoConsoleComponent);
bool TryGetBankAccount(int id, out CargoBankAccount account);
bool ChangeBalance(int id, int n);
}
}