predict StackSystem GetVerbsEvent (#39741)

This commit is contained in:
MarkerWicker
2025-08-18 17:49:25 -06:00
committed by GitHub
parent 020f25139c
commit 3323a17b3d
2 changed files with 54 additions and 40 deletions

View File

@@ -16,13 +16,9 @@ namespace Content.Server.Stack
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public static readonly int[] DefaultSplitAmounts = { 1, 5, 10, 20, 30, 50 };
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<StackComponent, GetVerbsEvent<AlternativeVerb>>(OnStackAlternativeInteract);
}
public override void SetCount(EntityUid uid, int amount, StackComponent? component = null)
@@ -165,42 +161,7 @@ namespace Content.Server.Stack
return amounts;
}
private void OnStackAlternativeInteract(EntityUid uid, StackComponent stack, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanAccess || !args.CanInteract || args.Hands == null || stack.Count == 1)
return;
AlternativeVerb halve = new()
{
Text = Loc.GetString("comp-stack-split-halve"),
Category = VerbCategory.Split,
Act = () => UserSplit(uid, args.User, stack.Count / 2, stack),
Priority = 1
};
args.Verbs.Add(halve);
var priority = 0;
foreach (var amount in DefaultSplitAmounts)
{
if (amount >= stack.Count)
continue;
AlternativeVerb verb = new()
{
Text = amount.ToString(),
Category = VerbCategory.Split,
Act = () => UserSplit(uid, args.User, amount, stack),
// we want to sort by size, not alphabetically by the verb text.
Priority = priority
};
priority--;
args.Verbs.Add(verb);
}
}
private void UserSplit(EntityUid uid, EntityUid userUid, int amount,
protected override void UserSplit(EntityUid uid, EntityUid userUid, int amount,
StackComponent? stack = null,
TransformComponent? userTransform = null)
{

View File

@@ -6,6 +6,7 @@ using Content.Shared.Interaction;
using Content.Shared.Nutrition;
using Content.Shared.Popups;
using Content.Shared.Storage.EntitySystems;
using Content.Shared.Verbs;
using JetBrains.Annotations;
using Robust.Shared.GameStates;
using Robust.Shared.Physics.Systems;
@@ -29,6 +30,8 @@ namespace Content.Shared.Stacks
[Dependency] protected readonly SharedPopupSystem Popup = default!;
[Dependency] private readonly SharedStorageSystem _storage = default!;
public static readonly int[] DefaultSplitAmounts = { 1, 5, 10, 20, 30, 50 };
public override void Initialize()
{
base.Initialize();
@@ -40,6 +43,7 @@ namespace Content.Shared.Stacks
SubscribeLocalEvent<StackComponent, InteractUsingEvent>(OnStackInteractUsing);
SubscribeLocalEvent<StackComponent, BeforeIngestedEvent>(OnBeforeEaten);
SubscribeLocalEvent<StackComponent, IngestedEvent>(OnEaten);
SubscribeLocalEvent<StackComponent, GetVerbsEvent<AlternativeVerb>>(OnStackAlternativeInteract);
_vvm.GetTypeHandler<StackComponent>()
.AddPath(nameof(StackComponent.Count), (_, comp) => comp.Count, SetCount);
@@ -432,6 +436,55 @@ namespace Content.Shared.Stacks
// Here to tell the food system to do destroy stuff.
args.Destroy = true;
}
private void OnStackAlternativeInteract(EntityUid uid, StackComponent stack, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanAccess || !args.CanInteract || args.Hands == null || stack.Count == 1)
return;
AlternativeVerb halve = new()
{
Text = Loc.GetString("comp-stack-split-halve"),
Category = VerbCategory.Split,
Act = () => UserSplit(uid, args.User, stack.Count / 2, stack),
Priority = 1
};
args.Verbs.Add(halve);
var priority = 0;
foreach (var amount in DefaultSplitAmounts)
{
if (amount >= stack.Count)
continue;
AlternativeVerb verb = new()
{
Text = amount.ToString(),
Category = VerbCategory.Split,
Act = () => UserSplit(uid, args.User, amount, stack),
// we want to sort by size, not alphabetically by the verb text.
Priority = priority
};
priority--;
args.Verbs.Add(verb);
}
}
/// <remarks>
/// OnStackAlternativeInteract() was moved to shared in order to faciliate prediction of stack splitting verbs.
/// However, prediction of interacitons with spawned entities is non-functional (or so i'm told)
/// So, UserSplit() and Split() should remain on the server for the time being.
/// This empty virtual method allows for UserSplit() to be called on the server from the client.
/// When prediction is improved, those two methods should be moved to shared, in order to predict the splitting itself (not just the verbs)
/// </remarks>
protected virtual void UserSplit(EntityUid uid, EntityUid userUid, int amount,
StackComponent? stack = null,
TransformComponent? userTransform = null)
{
}
}
/// <summary>