Chill bounties + fixes (#23411)

* Chill bounties + fixes

* localize

* fix arbitage
This commit is contained in:
Nemanja
2024-01-03 19:34:47 -05:00
committed by GitHub
parent 9d8ac7846a
commit 4662d463b8
22 changed files with 284 additions and 182 deletions

View File

@@ -2,14 +2,16 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Cargo.Components;
using Content.Server.Labels;
using Content.Server.NameIdentifier;
using Content.Server.Paper;
using Content.Shared.Cargo;
using Content.Shared.Cargo.Components;
using Content.Shared.Cargo.Prototypes;
using Content.Shared.Database;
using Content.Shared.NameIdentifier;
using Content.Shared.Stacks;
using JetBrains.Annotations;
using Robust.Server.Containers;
using Robust.Shared.Collections;
using Robust.Shared.Containers;
using Robust.Shared.Random;
using Robust.Shared.Utility;
@@ -19,6 +21,14 @@ namespace Content.Server.Cargo.Systems;
public sealed partial class CargoSystem
{
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly NameIdentifierSystem _nameIdentifier = default!;
[ValidatePrototypeId<NameIdentifierGroupPrototype>]
private const string BountyNameIdentifierGroup = "Bounty";
private EntityQuery<StackComponent> _stackQuery;
private EntityQuery<ContainerManagerComponent> _containerQuery;
private EntityQuery<CargoBountyLabelComponent> _bountyLabelQuery;
private void InitializeBounty()
{
@@ -27,6 +37,10 @@ public sealed partial class CargoSystem
SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
_stackQuery = GetEntityQuery<StackComponent>();
_containerQuery = GetEntityQuery<ContainerManagerComponent>();
_bountyLabelQuery = GetEntityQuery<CargoBountyLabelComponent>();
}
private void OnBountyConsoleOpened(EntityUid uid, CargoBountyConsoleComponent component, BoundUIOpenedEvent args)
@@ -98,7 +112,7 @@ public sealed partial class CargoSystem
if (!TryGetBountyFromId(station, component.Id, out var bounty, database))
return;
if (!_protoMan.TryIndex<CargoBountyPrototype>(bounty.Value.Bounty, out var bountyPrototype) ||
if (!_protoMan.TryIndex(bounty.Value.Bounty, out var bountyPrototype) ||
!IsBountyComplete(container.Owner, bountyPrototype))
return;
@@ -112,25 +126,15 @@ public sealed partial class CargoSystem
private void OnSold(ref EntitySoldEvent args)
{
var containerQuery = GetEntityQuery<ContainerManagerComponent>();
var labelQuery = GetEntityQuery<CargoBountyLabelComponent>();
foreach (var sold in args.Sold)
{
if (!containerQuery.TryGetComponent(sold, out var containerMan))
continue;
// make sure this label was actually applied to a crate.
if (!_container.TryGetContainer(sold, LabelSystem.ContainerName, out var container, containerMan))
continue;
if (container.ContainedEntities.FirstOrNull() is not { } label ||
!labelQuery.TryGetComponent(label, out var component))
if (!TryGetBountyLabel(sold, out _, out var component))
continue;
if (!TryGetBountyFromId(args.Station, component.Id, out var bounty))
continue;
if (!IsBountyComplete(container.Owner, bounty.Value))
if (!IsBountyComplete(sold, bounty.Value))
continue;
TryRemoveBounty(args.Station, bounty.Value);
@@ -139,6 +143,28 @@ public sealed partial class CargoSystem
}
}
private bool TryGetBountyLabel(EntityUid uid,
[NotNullWhen(true)] out EntityUid? labelEnt,
[NotNullWhen(true)] out CargoBountyLabelComponent? labelComp)
{
labelEnt = null;
labelComp = null;
if (!_containerQuery.TryGetComponent(uid, out var containerMan))
return false;
// make sure this label was actually applied to a crate.
if (!_container.TryGetContainer(uid, LabelSystem.ContainerName, out var container, containerMan))
return false;
if (container.ContainedEntities.FirstOrNull() is not { } label ||
!_bountyLabelQuery.TryGetComponent(label, out var component))
return false;
labelEnt = label;
labelComp = component;
return true;
}
private void OnMapInit(EntityUid uid, StationCargoBountyDatabaseComponent component, MapInitEvent args)
{
FillBountyDatabase(uid, component);
@@ -161,12 +187,53 @@ public sealed partial class CargoSystem
UpdateBountyConsoles();
}
public void RerollBountyDatabase(Entity<StationCargoBountyDatabaseComponent?> entity)
{
if (!Resolve(entity, ref entity.Comp))
return;
entity.Comp.Bounties.Clear();
FillBountyDatabase(entity);
}
public bool IsBountyComplete(EntityUid container, EntityUid? station, out HashSet<EntityUid> bountyEntities)
{
if (!TryGetBountyLabel(container, out _, out var component))
{
bountyEntities = new();
return false;
}
station ??= _station.GetOwningStation(container);
if (station == null)
{
bountyEntities = new();
return false;
}
if (!TryGetBountyFromId(station.Value, component.Id, out var bounty))
{
bountyEntities = new();
return false;
}
return IsBountyComplete(container, bounty.Value, out bountyEntities);
}
public bool IsBountyComplete(EntityUid container, CargoBountyData data)
{
if (!_protoMan.TryIndex<CargoBountyPrototype>(data.Bounty, out var proto))
return false;
return IsBountyComplete(container, data, out _);
}
return IsBountyComplete(container, proto.Entries);
public bool IsBountyComplete(EntityUid container, CargoBountyData data, out HashSet<EntityUid> bountyEntities)
{
if (!_protoMan.TryIndex(data.Bounty, out var proto))
{
bountyEntities = new();
return false;
}
return IsBountyComplete(container, proto.Entries, out bountyEntities);
}
public bool IsBountyComplete(EntityUid container, string id)
@@ -184,26 +251,18 @@ public sealed partial class CargoSystem
public bool IsBountyComplete(EntityUid container, IEnumerable<CargoBountyItemEntry> entries)
{
var contained = new HashSet<EntityUid>();
if (TryComp<ContainerManagerComponent>(container, out var containers))
{
foreach (var con in containers.Containers.Values)
{
if (con.ID == LabelSystem.ContainerName)
continue;
foreach (var ent in con.ContainedEntities)
{
contained.Add(ent);
}
}
}
return IsBountyComplete(contained, entries);
return IsBountyComplete(container, entries, out _);
}
public bool IsBountyComplete(HashSet<EntityUid> entities, IEnumerable<CargoBountyItemEntry> entries)
public bool IsBountyComplete(EntityUid container, IEnumerable<CargoBountyItemEntry> entries, out HashSet<EntityUid> bountyEntities)
{
return IsBountyComplete(GetBountyEntities(container), entries, out bountyEntities);
}
public bool IsBountyComplete(HashSet<EntityUid> entities, IEnumerable<CargoBountyItemEntry> entries, out HashSet<EntityUid> bountyEntities)
{
bountyEntities = new();
foreach (var entry in entries)
{
var count = 0;
@@ -215,7 +274,8 @@ public sealed partial class CargoSystem
{
if (!entry.Whitelist.IsValid(entity, EntityManager))
continue;
count++;
count += _stackQuery.CompOrNull(entity)?.Count ?? 1;
temp.Add(entity);
if (count >= entry.Amount)
@@ -228,17 +288,58 @@ public sealed partial class CargoSystem
foreach (var ent in temp)
{
entities.Remove(ent);
bountyEntities.Add(ent);
}
}
return true;
}
private HashSet<EntityUid> GetBountyEntities(EntityUid uid)
{
var entities = new HashSet<EntityUid>
{
uid
};
if (!TryComp<ContainerManagerComponent>(uid, out var containers))
return entities;
foreach (var container in containers.Containers.Values)
{
foreach (var ent in container.ContainedEntities)
{
if (_bountyLabelQuery.HasComponent(ent))
continue;
var children = GetBountyEntities(ent);
foreach (var child in children)
{
entities.Add(child);
}
}
}
return entities;
}
[PublicAPI]
public bool TryAddBounty(EntityUid uid, StationCargoBountyDatabaseComponent? component = null)
{
if (!Resolve(uid, ref component))
return false;
// todo: consider making the cargo bounties weighted.
var bounty = _random.Pick(_protoMan.EnumeratePrototypes<CargoBountyPrototype>().ToList());
var allBounties = _protoMan.EnumeratePrototypes<CargoBountyPrototype>().ToList();
var filteredBounties = new List<CargoBountyPrototype>();
foreach (var proto in allBounties)
{
if (component.Bounties.Any(b => b.Bounty == proto.ID))
continue;
filteredBounties.Add(proto);
}
var pool = filteredBounties.Count == 0 ? allBounties : filteredBounties;
var bounty = _random.Pick(pool);
return TryAddBounty(uid, bounty, component);
}
@@ -261,17 +362,15 @@ public sealed partial class CargoSystem
if (component.Bounties.Count >= component.MaxBounties)
return false;
var duration = MathF.Round(_random.NextFloat(component.MinBountyTime, component.MaxBountyTime) / 15) * 15;
var endTime = _timing.CurTime + TimeSpan.FromSeconds(duration);
component.Bounties.Add(new CargoBountyData(component.TotalBounties, bounty.ID, endTime));
_nameIdentifier.GenerateUniqueName(uid, BountyNameIdentifierGroup, out var randomVal);
component.Bounties.Add(new CargoBountyData(bounty, randomVal));
_adminLogger.Add(LogType.Action, LogImpact.Low, $"Added bounty \"{bounty.ID}\" (id:{component.TotalBounties}) to station {ToPrettyString(uid)}");
component.TotalBounties++;
return true;
}
[PublicAPI]
public bool TryRemoveBounty(EntityUid uid, int dataId, StationCargoBountyDatabaseComponent? component = null)
public bool TryRemoveBounty(EntityUid uid, string dataId, StationCargoBountyDatabaseComponent? component = null)
{
if (!TryGetBountyFromId(uid, dataId, out var data, component))
return false;
@@ -298,7 +397,7 @@ public sealed partial class CargoSystem
public bool TryGetBountyFromId(
EntityUid uid,
int id,
string id,
[NotNullWhen(true)] out CargoBountyData? bounty,
StationCargoBountyDatabaseComponent? component = null)
{
@@ -333,17 +432,9 @@ public sealed partial class CargoSystem
private void UpdateBounty()
{
var query = EntityQueryEnumerator<StationCargoBountyDatabaseComponent>();
while (query.MoveNext(out var uid, out var bountyDatabase))
while (query.MoveNext(out var bountyDatabase))
{
bountyDatabase.CheckedBounties.Clear();
var bounties = new ValueList<CargoBountyData>(bountyDatabase.Bounties);
foreach (var bounty in bounties)
{
if (_timing.CurTime < bounty.EndTime)
continue;
TryRemoveBounty(uid, bounty, bountyDatabase);
FillBountyDatabase(uid, bountyDatabase);
}
}
}
}