Generalized Store System (#10201)
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
using Content.Shared.Traitor.Uplink;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink.Account
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes when one of the UplinkAccounts changed its TC balance
|
||||
/// </summary>
|
||||
public sealed class UplinkAccountBalanceChanged : EntityEventArgs
|
||||
{
|
||||
public readonly UplinkAccount Account;
|
||||
|
||||
/// <summary>
|
||||
/// Difference between NewBalance - OldBalance
|
||||
/// </summary>
|
||||
public readonly int Difference;
|
||||
|
||||
public readonly int NewBalance;
|
||||
public readonly int OldBalance;
|
||||
|
||||
public UplinkAccountBalanceChanged(UplinkAccount account, int difference)
|
||||
{
|
||||
Account = account;
|
||||
Difference = difference;
|
||||
|
||||
NewBalance = account.Balance;
|
||||
OldBalance = account.Balance - difference;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Traitor.Uplink;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink.Account
|
||||
{
|
||||
/// <summary>
|
||||
/// Manage all registred uplink accounts and their balance
|
||||
/// </summary>
|
||||
public sealed class UplinkAccountsSystem : EntitySystem
|
||||
{
|
||||
public const string TelecrystalProtoId = "Telecrystal";
|
||||
|
||||
[Dependency]
|
||||
private readonly UplinkListingSytem _listingSystem = default!;
|
||||
[Dependency]
|
||||
private readonly SharedStackSystem _stackSystem = default!;
|
||||
|
||||
private readonly HashSet<UplinkAccount> _accounts = new();
|
||||
|
||||
public bool AddNewAccount(UplinkAccount acc)
|
||||
{
|
||||
return _accounts.Add(acc);
|
||||
}
|
||||
|
||||
public bool HasAccount(EntityUid holder) =>
|
||||
_accounts.Any(acct => acct.AccountHolder == holder);
|
||||
|
||||
/// <summary>
|
||||
/// Add TC to uplinks account balance
|
||||
/// </summary>
|
||||
public bool AddToBalance(UplinkAccount account, int toAdd)
|
||||
{
|
||||
account.Balance += toAdd;
|
||||
|
||||
RaiseLocalEvent(new UplinkAccountBalanceChanged(account, toAdd));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Charge TC from uplinks account balance
|
||||
/// </summary>
|
||||
public bool RemoveFromBalance(UplinkAccount account, int price)
|
||||
{
|
||||
if (account.Balance - price < 0)
|
||||
return false;
|
||||
|
||||
account.Balance -= price;
|
||||
|
||||
RaiseLocalEvent(new UplinkAccountBalanceChanged(account, -price));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force-set TC uplinks account balance to a new value
|
||||
/// </summary>
|
||||
public bool SetBalance(UplinkAccount account, int newBalance)
|
||||
{
|
||||
if (newBalance < 0)
|
||||
return false;
|
||||
|
||||
var dif = newBalance - account.Balance;
|
||||
account.Balance = newBalance;
|
||||
RaiseLocalEvent(new UplinkAccountBalanceChanged(account, dif));
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public bool TryPurchaseItem(UplinkAccount acc, string itemId, EntityCoordinates spawnCoords, [NotNullWhen(true)] out EntityUid? purchasedItem)
|
||||
{
|
||||
purchasedItem = null;
|
||||
|
||||
if (!_listingSystem.TryGetListing(itemId, out var listing))
|
||||
return false;
|
||||
|
||||
if (acc.Balance < listing.Price)
|
||||
return false;
|
||||
|
||||
if (!RemoveFromBalance(acc, listing.Price))
|
||||
return false;
|
||||
|
||||
purchasedItem = EntityManager.SpawnEntity(listing.ItemId, spawnCoords);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryWithdrawTC(UplinkAccount acc, int tc, EntityCoordinates spawnCoords, [NotNullWhen(true)] out EntityUid? stackUid)
|
||||
{
|
||||
stackUid = null;
|
||||
|
||||
// try to charge TC from players account
|
||||
var actTC = Math.Min(tc, acc.Balance);
|
||||
if (actTC <= 0)
|
||||
return false;
|
||||
if (!RemoveFromBalance(acc, actTC))
|
||||
return false;
|
||||
|
||||
// create a stack of TCs near player
|
||||
var stackEntity = EntityManager.SpawnEntity(TelecrystalProtoId, spawnCoords);
|
||||
stackUid = stackEntity;
|
||||
|
||||
// set right amount in stack
|
||||
_stackSystem.SetCount(stackUid.Value, actTC);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Traitor.Uplink.Account;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Traitor.Uplink;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Console;
|
||||
@@ -82,15 +81,10 @@ namespace Content.Server.Traitor.Uplink.Commands
|
||||
// Get TC count
|
||||
var configManager = IoCManager.Resolve<IConfigurationManager>();
|
||||
var tcCount = configManager.GetCVar(CCVars.TraitorStartingBalance);
|
||||
|
||||
// Get account
|
||||
var uplinkAccount = new UplinkAccount(tcCount, user);
|
||||
var accounts = entityManager.EntitySysManager.GetEntitySystem<UplinkAccountsSystem>();
|
||||
accounts.AddNewAccount(uplinkAccount);
|
||||
|
||||
Logger.Debug(entityManager.ToPrettyString(user));
|
||||
// Finally add uplink
|
||||
if (!entityManager.EntitySysManager.GetEntitySystem<UplinkSystem>()
|
||||
.AddUplink(user, uplinkAccount, uplinkEntity))
|
||||
var uplinkSys = entityManager.EntitySysManager.GetEntitySystem<UplinkSystem>();
|
||||
if (!uplinkSys.AddUplink(user, FixedPoint2.New(tcCount), uplinkEntity: uplinkEntity))
|
||||
{
|
||||
shell.WriteLine(Loc.GetString("add-uplink-command-error-2"));
|
||||
return;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using Content.Shared.Store;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink.SurplusBundle;
|
||||
|
||||
/// <summary>
|
||||
@@ -12,4 +15,11 @@ public sealed class SurplusBundleComponent : Component
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
[DataField("totalPrice")]
|
||||
public int TotalPrice = 20;
|
||||
|
||||
/// <summary>
|
||||
/// The preset that will be used to get all the listings.
|
||||
/// Currently just defaults to the basic uplink.
|
||||
/// </summary>
|
||||
[DataField("storePreset", customTypeSerializer: typeof(PrototypeIdSerializer<StorePresetPrototype>))]
|
||||
public string StorePreset = "StorePresetUplink";
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
using Content.Shared.PDA;
|
||||
using Content.Shared.Store;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
@@ -12,23 +13,25 @@ public sealed class SurplusBundleSystem : EntitySystem
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||
[Dependency] private readonly StoreSystem _store = default!;
|
||||
|
||||
private UplinkStoreListingPrototype[] _uplinks = default!;
|
||||
private ListingData[] _listings = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<SurplusBundleComponent, MapInitEvent>(OnMapInit);
|
||||
|
||||
InitList();
|
||||
SubscribeLocalEvent<SurplusBundleComponent, ComponentInit>(OnInit);
|
||||
}
|
||||
|
||||
private void InitList()
|
||||
private void OnInit(EntityUid uid, SurplusBundleComponent component, ComponentInit args)
|
||||
{
|
||||
// sort data in price descending order
|
||||
_uplinks = _prototypeManager.EnumeratePrototypes<UplinkStoreListingPrototype>()
|
||||
.Where(item => item.CanSurplus).ToArray();
|
||||
Array.Sort(_uplinks, (a, b) => b.Price - a.Price);
|
||||
var storePreset = _prototypeManager.Index<StorePresetPrototype>(component.StorePreset);
|
||||
|
||||
_listings = _store.GetAvailableListings(uid, null, storePreset.Categories).ToArray();
|
||||
|
||||
Array.Sort(_listings, (a, b) => (int) (b.Cost.Values.Sum() - a.Cost.Values.Sum())); //this might get weird with multicurrency but don't think about it
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, SurplusBundleComponent component, MapInitEvent args)
|
||||
@@ -46,19 +49,19 @@ public sealed class SurplusBundleSystem : EntitySystem
|
||||
var content = GetRandomContent(component.TotalPrice);
|
||||
foreach (var item in content)
|
||||
{
|
||||
var ent = EntityManager.SpawnEntity(item.ItemId, cords);
|
||||
var ent = EntityManager.SpawnEntity(item.ProductEntity, cords);
|
||||
_entityStorage.Insert(ent, component.Owner);
|
||||
}
|
||||
}
|
||||
|
||||
// wow, is this leetcode reference?
|
||||
private List<UplinkStoreListingPrototype> GetRandomContent(int targetCost)
|
||||
private List<ListingData> GetRandomContent(FixedPoint2 targetCost)
|
||||
{
|
||||
var ret = new List<UplinkStoreListingPrototype>();
|
||||
if (_uplinks.Length == 0)
|
||||
var ret = new List<ListingData>();
|
||||
if (_listings.Length == 0)
|
||||
return ret;
|
||||
|
||||
var totalCost = 0;
|
||||
var totalCost = FixedPoint2.Zero;
|
||||
var index = 0;
|
||||
while (totalCost < targetCost)
|
||||
{
|
||||
@@ -66,10 +69,10 @@ public sealed class SurplusBundleSystem : EntitySystem
|
||||
// Find new item with the lowest acceptable price
|
||||
// All expansive items will be before index, all acceptable after
|
||||
var remainingBudget = targetCost - totalCost;
|
||||
while (_uplinks[index].Price > remainingBudget)
|
||||
while (_listings[index].Cost.Values.Sum() > remainingBudget)
|
||||
{
|
||||
index++;
|
||||
if (index >= _uplinks.Length)
|
||||
if (index >= _listings.Length)
|
||||
{
|
||||
// Looks like no cheap items left
|
||||
// It shouldn't be case for ss14 content
|
||||
@@ -79,10 +82,10 @@ public sealed class SurplusBundleSystem : EntitySystem
|
||||
}
|
||||
|
||||
// Select random listing and add into crate
|
||||
var randomIndex = _random.Next(index, _uplinks.Length);
|
||||
var randomItem = _uplinks[randomIndex];
|
||||
var randomIndex = _random.Next(index, _listings.Length);
|
||||
var randomItem = _listings[randomIndex];
|
||||
ret.Add(randomItem);
|
||||
totalCost += randomItem.Price;
|
||||
totalCost += randomItem.Cost.Values.Sum();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Content.Server.Traitor.Uplink.Telecrystal
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class TelecrystalComponent : Component
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using Content.Server.Traitor.Uplink.Account;
|
||||
using Content.Server.Traitor.Uplink.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Stacks;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink.Telecrystal
|
||||
{
|
||||
public sealed class TelecrystalSystem : EntitySystem
|
||||
{
|
||||
[Dependency]
|
||||
private readonly UplinkAccountsSystem _accounts = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<TelecrystalComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
}
|
||||
|
||||
private void OnAfterInteract(EntityUid uid, TelecrystalComponent component, AfterInteractEvent args)
|
||||
{
|
||||
if (args.Handled || !args.CanReach)
|
||||
return;
|
||||
|
||||
if (args.Target == null || !EntityManager.TryGetComponent(args.Target.Value, out UplinkComponent? uplink))
|
||||
return;
|
||||
|
||||
// TODO: when uplink will have some auth logic (like PDA ringtone code)
|
||||
// check if uplink open before adding TC
|
||||
// No metagaming by using this on every PDA around just to see if it gets used up.
|
||||
|
||||
var acc = uplink.UplinkAccount;
|
||||
if (acc == null)
|
||||
return;
|
||||
|
||||
EntityManager.TryGetComponent(uid, out SharedStackComponent? stack);
|
||||
|
||||
var tcCount = stack != null ? stack.Count : 1;
|
||||
if (!_accounts.AddToBalance(acc, tcCount))
|
||||
return;
|
||||
|
||||
var msg = Loc.GetString("telecrystal-component-sucs-inserted",
|
||||
("source", args.Used), ("target", args.Target));
|
||||
|
||||
args.User.PopupMessage(args.User, msg);
|
||||
|
||||
EntityManager.DeleteEntity(uid);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.Traitor.Uplink;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class UplinkComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
[DataField("buySuccessSound")]
|
||||
public SoundSpecifier BuySuccessSound = new SoundPathSpecifier("/Audio/Effects/kaching.ogg");
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("insufficientFundsSound")]
|
||||
public SoundSpecifier InsufficientFundsSound = new SoundPathSpecifier("/Audio/Effects/error.ogg");
|
||||
|
||||
[DataField("activatesInHands")]
|
||||
public bool ActivatesInHands = false;
|
||||
|
||||
[DataField("presetInfo")]
|
||||
public PresetUplinkInfo? PresetInfo = null;
|
||||
|
||||
[ViewVariables] public UplinkAccount? UplinkAccount;
|
||||
|
||||
[ViewVariables, DataField("jobWhiteList", customTypeSerializer:typeof(PrototypeIdHashSetSerializer<JobPrototype>))]
|
||||
public HashSet<string>? JobWhitelist = null;
|
||||
|
||||
[Serializable]
|
||||
[DataDefinition]
|
||||
public sealed class PresetUplinkInfo
|
||||
{
|
||||
[DataField("balance")]
|
||||
public int StartingBalance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Content.Server.Traitor.Uplink.Components;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink
|
||||
{
|
||||
public sealed class UplinkInitEvent : EntityEventArgs
|
||||
{
|
||||
public UplinkComponent Uplink;
|
||||
|
||||
public UplinkInitEvent(UplinkComponent uplink)
|
||||
{
|
||||
Uplink = uplink;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UplinkRemovedEvent : EntityEventArgs
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using Content.Shared.PDA;
|
||||
using Content.Shared.Traitor.Uplink;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains and controls all items in traitors uplink shop
|
||||
/// </summary>
|
||||
public sealed class UplinkListingSytem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
private readonly Dictionary<string, UplinkListingData> _listings = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
foreach (var item in _prototypeManager.EnumeratePrototypes<UplinkStoreListingPrototype>())
|
||||
{
|
||||
var newListing = new UplinkListingData(item.ListingName, item.ItemId,
|
||||
item.Price, item.Category, item.Description, item.Icon, item.JobWhitelist);
|
||||
|
||||
RegisterUplinkListing(newListing);
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterUplinkListing(UplinkListingData listing)
|
||||
{
|
||||
if (!ContainsListing(listing))
|
||||
{
|
||||
_listings.Add(listing.ItemId, listing);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsListing(UplinkListingData listing)
|
||||
{
|
||||
return _listings.ContainsKey(listing.ItemId);
|
||||
}
|
||||
|
||||
public bool TryGetListing(string itemID, [NotNullWhen(true)] out UplinkListingData? data)
|
||||
{
|
||||
return _listings.TryGetValue(itemID, out data);
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, UplinkListingData> GetListings()
|
||||
{
|
||||
return _listings;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,230 +1,41 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Traitor.Uplink.Account;
|
||||
using Content.Server.Traitor.Uplink.Components;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.PDA;
|
||||
using Content.Shared.Traitor.Uplink;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Shared.FixedPoint;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink
|
||||
{
|
||||
public sealed class UplinkSystem : EntitySystem
|
||||
{
|
||||
[Dependency]
|
||||
private readonly UplinkAccountsSystem _accounts = default!;
|
||||
[Dependency]
|
||||
private readonly UplinkListingSytem _listing = default!;
|
||||
|
||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly StoreSystem _store = default!;
|
||||
|
||||
public override void Initialize()
|
||||
public const string TelecrystalCurrencyPrototype = "Telecrystal";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of TC on an "uplink"
|
||||
/// Mostly just here for legacy systems based on uplink.
|
||||
/// </summary>
|
||||
/// <param name="component"></param>
|
||||
/// <returns>the amount of TC</returns>
|
||||
public int GetTCBalance(StoreComponent component)
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<UplinkComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<UplinkComponent, ComponentRemove>(OnRemove);
|
||||
SubscribeLocalEvent<UplinkComponent, ActivateInWorldEvent>(OnActivate);
|
||||
|
||||
// UI events
|
||||
SubscribeLocalEvent<UplinkComponent, UplinkBuyListingMessage>(OnBuy);
|
||||
SubscribeLocalEvent<UplinkComponent, UplinkRequestUpdateInterfaceMessage>(OnRequestUpdateUI);
|
||||
SubscribeLocalEvent<UplinkComponent, UplinkTryWithdrawTC>(OnWithdrawTC);
|
||||
|
||||
SubscribeLocalEvent<UplinkAccountBalanceChanged>(OnBalanceChangedBroadcast);
|
||||
FixedPoint2? tcBalance = component.Balance.GetValueOrDefault(TelecrystalCurrencyPrototype);
|
||||
return tcBalance != null ? tcBalance.Value.Int() : 0;
|
||||
}
|
||||
|
||||
public void SetAccount(UplinkComponent component, UplinkAccount account)
|
||||
{
|
||||
if (component.UplinkAccount != null)
|
||||
{
|
||||
Logger.Error("Can't init one uplink with different account!");
|
||||
return;
|
||||
}
|
||||
|
||||
component.UplinkAccount = account;
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, UplinkComponent component, ComponentInit args)
|
||||
{
|
||||
RaiseLocalEvent(uid, new UplinkInitEvent(component), true);
|
||||
|
||||
// if component has a preset info (probably spawn by admin)
|
||||
// create a new account and register it for this uplink
|
||||
if (component.PresetInfo != null)
|
||||
{
|
||||
var account = new UplinkAccount(component.PresetInfo.StartingBalance);
|
||||
_accounts.AddNewAccount(account);
|
||||
SetAccount(component, account);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRemove(EntityUid uid, UplinkComponent component, ComponentRemove args)
|
||||
{
|
||||
RaiseLocalEvent(uid, new UplinkRemovedEvent(), true);
|
||||
}
|
||||
|
||||
private void OnActivate(EntityUid uid, UplinkComponent component, ActivateInWorldEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
// check if uplinks activates directly or use some proxy, like a PDA
|
||||
if (!component.ActivatesInHands)
|
||||
return;
|
||||
if (component.UplinkAccount == null)
|
||||
return;
|
||||
|
||||
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
|
||||
return;
|
||||
|
||||
ToggleUplinkUI(component, actor.PlayerSession);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnBalanceChangedBroadcast(UplinkAccountBalanceChanged ev)
|
||||
{
|
||||
foreach (var uplink in EntityManager.EntityQuery<UplinkComponent>())
|
||||
{
|
||||
if (uplink.UplinkAccount == ev.Account)
|
||||
{
|
||||
UpdateUserInterface(uplink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRequestUpdateUI(EntityUid uid, UplinkComponent uplink, UplinkRequestUpdateInterfaceMessage args)
|
||||
{
|
||||
UpdateUserInterface(uplink);
|
||||
}
|
||||
|
||||
private void OnBuy(EntityUid uid, UplinkComponent uplink, UplinkBuyListingMessage message)
|
||||
{
|
||||
if (message.Session.AttachedEntity is not { Valid: true } player) return;
|
||||
if (uplink.UplinkAccount == null) return;
|
||||
|
||||
if (!_accounts.TryPurchaseItem(uplink.UplinkAccount, message.ItemId,
|
||||
EntityManager.GetComponent<TransformComponent>(player).Coordinates, out var entity))
|
||||
{
|
||||
SoundSystem.Play(uplink.InsufficientFundsSound.GetSound(),
|
||||
Filter.SinglePlayer(message.Session), uplink.Owner, AudioParams.Default);
|
||||
RaiseNetworkEvent(new UplinkInsufficientFundsMessage(), message.Session.ConnectedClient);
|
||||
return;
|
||||
}
|
||||
|
||||
_handsSystem.PickupOrDrop(player, entity.Value);
|
||||
|
||||
SoundSystem.Play(uplink.BuySuccessSound.GetSound(),
|
||||
Filter.SinglePlayer(message.Session), uplink.Owner, AudioParams.Default.WithVolume(-8f));
|
||||
|
||||
RaiseNetworkEvent(new UplinkBuySuccessMessage(), message.Session.ConnectedClient);
|
||||
}
|
||||
|
||||
private void OnWithdrawTC(EntityUid uid, UplinkComponent uplink, UplinkTryWithdrawTC args)
|
||||
{
|
||||
var acc = uplink.UplinkAccount;
|
||||
if (acc == null)
|
||||
return;
|
||||
|
||||
if (args.Session.AttachedEntity is not { Valid: true } player) return;
|
||||
var cords = EntityManager.GetComponent<TransformComponent>(player).Coordinates;
|
||||
|
||||
// try to withdraw TCs from account
|
||||
if (!_accounts.TryWithdrawTC(acc, args.TC, cords, out var tcUid))
|
||||
return;
|
||||
|
||||
// try to put it into players hands
|
||||
_handsSystem.PickupOrDrop(player, tcUid.Value);
|
||||
|
||||
// play buying sound
|
||||
SoundSystem.Play(uplink.BuySuccessSound.GetSound(),
|
||||
Filter.SinglePlayer(args.Session), uplink.Owner, AudioParams.Default.WithVolume(-8f));
|
||||
|
||||
UpdateUserInterface(uplink);
|
||||
}
|
||||
|
||||
public void ToggleUplinkUI(UplinkComponent component, IPlayerSession session)
|
||||
{
|
||||
var ui = component.Owner.GetUIOrNull(UplinkUiKey.Key);
|
||||
ui?.Toggle(session);
|
||||
|
||||
UpdateUserInterface(component);
|
||||
}
|
||||
|
||||
private void UpdateUserInterface(UplinkComponent component)
|
||||
{
|
||||
var ui = component.Owner.GetUIOrNull(UplinkUiKey.Key);
|
||||
if (ui == null)
|
||||
return;
|
||||
|
||||
var listings = _listing.GetListings().Values.ToList();
|
||||
var acc = component.UplinkAccount;
|
||||
|
||||
UplinkAccountData accData;
|
||||
if (acc != null)
|
||||
{
|
||||
// if we don't have a jobwhitelist stored, get a new one
|
||||
if (component.JobWhitelist == null &&
|
||||
acc.AccountHolder != null &&
|
||||
TryComp<MindComponent>(acc.AccountHolder, out var mind) &&
|
||||
mind.Mind != null)
|
||||
{
|
||||
HashSet<string>? jobList = new();
|
||||
foreach (var role in mind.Mind.AllRoles.ToList())
|
||||
{
|
||||
if (role.GetType() == typeof(Job))
|
||||
{
|
||||
var job = (Job) role;
|
||||
jobList.Add(job.Prototype.ID);
|
||||
}
|
||||
}
|
||||
component.JobWhitelist = jobList;
|
||||
}
|
||||
|
||||
// filter out items not on the whitelist
|
||||
for (var i = 0; i < listings.Count; i++)
|
||||
{
|
||||
var entry = listings[i];
|
||||
if (entry.JobWhitelist != null)
|
||||
{
|
||||
var found = false;
|
||||
if (component.JobWhitelist != null)
|
||||
{
|
||||
foreach (var job in component.JobWhitelist)
|
||||
{
|
||||
if (entry.JobWhitelist.Contains(job))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
listings.Remove(entry);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
accData = new UplinkAccountData(acc.AccountHolder, acc.Balance);
|
||||
}
|
||||
else
|
||||
{
|
||||
accData = new UplinkAccountData(null, 0);
|
||||
}
|
||||
|
||||
ui.SetState(new UplinkUpdateState(accData, listings.ToArray()));
|
||||
}
|
||||
|
||||
public bool AddUplink(EntityUid user, UplinkAccount account, EntityUid? uplinkEntity = null)
|
||||
/// <summary>
|
||||
/// Adds an uplink to the target
|
||||
/// </summary>
|
||||
/// <param name="user">The person who is getting the uplink</param>
|
||||
/// <param name="balance">The amount of currency on the uplink. If null, will just use the amount specified in the preset.</param>
|
||||
/// <param name="uplinkPresetId">The id of the storepreset</param>
|
||||
/// <param name="uplinkEntity">The entity that will actually have the uplink functionality. Defaults to the PDA if null.</param>
|
||||
/// <returns>Whether or not the uplink was added successfully</returns>
|
||||
public bool AddUplink(EntityUid user, FixedPoint2? balance, string uplinkPresetId = "StorePresetUplink", EntityUid? uplinkEntity = null)
|
||||
{
|
||||
// Try to find target item
|
||||
if (uplinkEntity == null)
|
||||
@@ -234,11 +45,17 @@ namespace Content.Server.Traitor.Uplink
|
||||
return false;
|
||||
}
|
||||
|
||||
var uplink = uplinkEntity.Value.EnsureComponent<UplinkComponent>();
|
||||
SetAccount(uplink, account);
|
||||
var store = EnsureComp<StoreComponent>(uplinkEntity.Value);
|
||||
_store.InitializeFromPreset(uplinkPresetId, store);
|
||||
store.AccountOwner = user;
|
||||
store.Balance.Clear();
|
||||
|
||||
if (!HasComp<PDAComponent>(uplinkEntity.Value))
|
||||
uplink.ActivatesInHands = true;
|
||||
if (balance != null)
|
||||
{
|
||||
store.Balance.Clear();
|
||||
_store.TryAddCurrency(
|
||||
new Dictionary<string, FixedPoint2>() { { TelecrystalCurrencyPrototype, balance.Value } }, store);
|
||||
}
|
||||
|
||||
// TODO add BUI. Currently can't be done outside of yaml -_-
|
||||
|
||||
@@ -248,14 +65,13 @@ namespace Content.Server.Traitor.Uplink
|
||||
private EntityUid? FindUplinkTarget(EntityUid user)
|
||||
{
|
||||
// Try to find PDA in inventory
|
||||
|
||||
if (_inventorySystem.TryGetContainerSlotEnumerator(user, out var containerSlotEnumerator))
|
||||
{
|
||||
while (containerSlotEnumerator.MoveNext(out var pdaUid))
|
||||
{
|
||||
if (!pdaUid.ContainedEntity.HasValue) continue;
|
||||
|
||||
if (HasComp<PDAComponent>(pdaUid.ContainedEntity.Value))
|
||||
if (HasComp<PDAComponent>(pdaUid.ContainedEntity.Value) || HasComp<StoreComponent>(pdaUid.ContainedEntity.Value))
|
||||
return pdaUid.ContainedEntity.Value;
|
||||
}
|
||||
}
|
||||
@@ -263,7 +79,7 @@ namespace Content.Server.Traitor.Uplink
|
||||
// Also check hands
|
||||
foreach (var item in _handsSystem.EnumerateHeld(user))
|
||||
{
|
||||
if (HasComp<PDAComponent>(item))
|
||||
if (HasComp<PDAComponent>(item) || HasComp<StoreComponent>(item))
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user