-
-
Notifications
You must be signed in to change notification settings - Fork 63
Система удержания #928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
ThereDrD0
wants to merge
9
commits into
master
Choose a base branch
from
add/multipulling
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Система удержания #928
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
83a907e
fix: scp096 stuck
ThereDrD0 349160b
add: multi pulling v1
ThereDrD0 692606e
add: tweaks and QoL
ThereDrD0 e943403
add: update with many features
ThereDrD0 0a3d1ad
remove: actions
ThereDrD0 573ff17
Merge branch 'master' into add/multipulling
ThereDrD0 7427c1f
Merge branch 'master' into add/multipulling
ThereDrD0 9759c56
add: add whitelist/blaclist
ThereDrD0 e43a8f6
add: damn update. Added action blocking, code refactor
ThereDrD0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
185 changes: 185 additions & 0 deletions
185
Content.Client/_Scp/Holding/ScpHoldingPredictionSystem.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,185 @@ | ||
| using System; | ||
| using Content.Shared._Scp.Holding; | ||
| using Content.Shared.Hands; | ||
| using Content.Shared.Hands.Components; | ||
| using Content.Shared.Hands.EntitySystems; | ||
| using Content.Shared.Inventory.VirtualItem; | ||
| using Robust.Client.Physics; | ||
| using Robust.Client.Player; | ||
| using Robust.Shared.Timing; | ||
|
|
||
| namespace Content.Client._Scp.Holding; | ||
|
|
||
| public sealed class ScpHoldingPredictionSystem : EntitySystem | ||
| { | ||
| [Dependency] private readonly SharedScpHoldingSystem _holding = default!; | ||
| [Dependency] private readonly SharedHandsSystem _hands = default!; | ||
| [Dependency] private readonly Robust.Client.Physics.PhysicsSystem _physics = default!; | ||
| [Dependency] private readonly IPlayerManager _player = default!; | ||
| [Dependency] private readonly IGameTiming _timing = default!; | ||
| [Dependency] private readonly SharedVirtualItemSystem _virtualItem = default!; | ||
|
|
||
| private static readonly TimeSpan BlockerRespawnSuppressionDuration = TimeSpan.FromSeconds(0.5); | ||
|
|
||
| private EntityUid? _suppressedHolder; | ||
| private EntityUid? _suppressedTarget; | ||
| private TimeSpan _suppressedUntil; | ||
|
|
||
| private EntityQuery<HandsComponent> _handsQuery; | ||
| private EntityQuery<ScpHolderComponent> _holderQuery; | ||
|
|
||
| public override void Initialize() | ||
| { | ||
| base.Initialize(); | ||
|
|
||
| _handsQuery = GetEntityQuery<HandsComponent>(); | ||
| _holderQuery = GetEntityQuery<ScpHolderComponent>(); | ||
|
|
||
| SubscribeLocalEvent<ScpHeldComponent, AfterAutoHandleStateEvent>(OnHeldAfterState); | ||
| SubscribeLocalEvent<ScpHoldHandBlockerComponent, GotUnequippedHandEvent>(OnBlockerUnequipped); | ||
| SubscribeLocalEvent<ScpHolderComponent, AfterAutoHandleStateEvent>(OnHolderAfterState); | ||
| SubscribeLocalEvent<ScpHeldComponent, UpdateIsPredictedEvent>(OnUpdateHeldPredicted); | ||
| } | ||
|
|
||
| public override void Update(float frameTime) | ||
| { | ||
| base.Update(frameTime); | ||
|
|
||
| if (_timing.CurTime >= _suppressedUntil) | ||
| ClearBlockerRespawnSuppression(); | ||
|
|
||
| var query = EntityQueryEnumerator<ScpHeldComponent>(); | ||
| while (query.MoveNext(out var uid, out _)) | ||
| { | ||
| _physics.UpdateIsPredicted(uid); | ||
| } | ||
|
|
||
| if (_player.LocalEntity is not { Valid: true } local) | ||
| { | ||
| ClearBlockerRespawnSuppression(); | ||
| return; | ||
| } | ||
|
|
||
| if (ShouldSuppressBlockerRespawn(local, _suppressedTarget)) | ||
| DeleteSuppressedBlockers(local, _suppressedTarget!.Value); | ||
|
|
||
| if (!_holderQuery.TryComp(local, out var localHolder)) | ||
| return; | ||
|
|
||
| if (ShouldSuppressBlockerRespawn(local, localHolder.Target)) | ||
| { | ||
| DeleteSuppressedBlockers(local, localHolder.Target!.Value); | ||
| return; | ||
| } | ||
|
|
||
| _holding.RefreshHolderState((local, localHolder)); | ||
| } | ||
|
|
||
| private void OnHeldAfterState(Entity<ScpHeldComponent> ent, ref AfterAutoHandleStateEvent args) | ||
| { | ||
| _holding.RefreshHeldState(ent); | ||
| } | ||
|
|
||
| private void OnHolderAfterState(Entity<ScpHolderComponent> ent, ref AfterAutoHandleStateEvent args) | ||
| { | ||
| if (ShouldSuppressBlockerRespawn(ent.Owner, ent.Comp.Target)) | ||
| { | ||
| DeleteSuppressedBlockers(ent.Owner, ent.Comp.Target!.Value); | ||
| return; | ||
| } | ||
|
|
||
| _holding.RefreshHolderState(ent); | ||
| } | ||
|
|
||
| private void OnBlockerUnequipped(Entity<ScpHoldHandBlockerComponent> ent, ref GotUnequippedHandEvent args) | ||
| { | ||
| if (_player.LocalEntity != args.User) | ||
| return; | ||
|
|
||
| if (_holderQuery.TryComp(args.User, out var holder)) | ||
| { | ||
| if (holder.Target == ent.Comp.Target) | ||
| return; | ||
| } | ||
|
|
||
| SuppressBlockerRespawn(args.User, ent.Comp.Target); | ||
| } | ||
|
|
||
| private void OnUpdateHeldPredicted(Entity<ScpHeldComponent> ent, ref UpdateIsPredictedEvent args) | ||
| { | ||
| if (_player.LocalEntity is not { Valid: true } local) | ||
| return; | ||
|
|
||
| if (ent.Owner == local) | ||
| { | ||
| args.IsPredicted = true; | ||
| return; | ||
| } | ||
|
|
||
| if (_holderQuery.TryComp(local, out var localHolder)) | ||
| { | ||
| if (localHolder.Target == ent.Owner) | ||
| { | ||
| args.IsPredicted = true; | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| for (var i = 0; i < ent.Comp.Holders.Count; i++) | ||
| { | ||
| if (ent.Comp.Holders[i] != local) | ||
| continue; | ||
|
|
||
| args.IsPredicted = true; | ||
| return; | ||
| } | ||
|
|
||
| if (ent.Comp.Holders.Count > 0) | ||
| args.BlockPrediction = true; | ||
| } | ||
|
|
||
| private void SuppressBlockerRespawn(EntityUid holder, EntityUid target) | ||
| { | ||
| _suppressedHolder = holder; | ||
| _suppressedTarget = target; | ||
| _suppressedUntil = _timing.CurTime + BlockerRespawnSuppressionDuration; | ||
| } | ||
|
|
||
| private void ClearBlockerRespawnSuppression() | ||
| { | ||
| _suppressedHolder = null; | ||
| _suppressedTarget = null; | ||
| _suppressedUntil = TimeSpan.Zero; | ||
| } | ||
|
|
||
| private bool ShouldSuppressBlockerRespawn(EntityUid holder, EntityUid? target) | ||
| { | ||
| return _suppressedHolder == holder && | ||
| _suppressedTarget != null && | ||
| target == _suppressedTarget && | ||
| _timing.CurTime < _suppressedUntil; | ||
| } | ||
|
|
||
| private void DeleteSuppressedBlockers(EntityUid holder, EntityUid target) | ||
| { | ||
| if (!_handsQuery.TryComp(holder, out var hands)) | ||
| return; | ||
|
|
||
| foreach (var heldItem in _hands.EnumerateHeld((holder, hands))) | ||
| { | ||
| if (!TryComp<VirtualItemComponent>(heldItem, out var virtualItem)) | ||
| continue; | ||
|
|
||
| if (!TryComp<ScpHoldHandBlockerComponent>(heldItem, out var blocker)) | ||
| continue; | ||
|
|
||
| if (virtualItem.BlockingEntity != target) | ||
| continue; | ||
|
|
||
| if (blocker.Target != target) | ||
| continue; | ||
|
|
||
| _virtualItem.DeleteVirtualItem((heldItem, virtualItem), holder); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не привязывайте suppression blocker'а к фиксированным 500 мс.
При RTT выше 500 мс
_suppressedUntilистечёт раньше, чем приедет authoritative состояние holder'а, и виртуальный blocker снова начнёт респавниться/мигать на клиенте. Здесь безопаснее держать suppression до сменыScpHolderComponent.Targetили удаленияScpHolderComponent, а не по wall-clock таймауту.Also applies to: 48-50, 141-160
🤖 Prompt for AI Agents