Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream' into Sensei
Browse files Browse the repository at this point in the history
  • Loading branch information
Nik_tos112 committed Sep 29, 2023
2 parents ddd31fd + 93eb5f6 commit 1ab1b11
Show file tree
Hide file tree
Showing 797 changed files with 33,562 additions and 45,095 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/update-wiki.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,12 @@ jobs:
username: ${{ secrets.WIKI_BOT_USER }}
password: ${{ secrets.WIKI_BOT_PASS }}

- name: Upload entity_prototypes.json to wiki
uses: jtmullen/[email protected]
with:
wiki_text_file: ./bin/Content.Server/data/entity_prototypes.json
edit_summary: Update entity_prototypes.json via GitHub Actions
page_name: "${{ secrets.WIKI_PAGE_ROOT }}/entity_prototypes.json"
api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php
username: ${{ secrets.WIKI_BOT_USER }}
password: ${{ secrets.WIKI_BOT_PASS }}
261 changes: 113 additions & 148 deletions Content.Client/Actions/ActionsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Containers;
using Robust.Shared.ContentPack;
using Robust.Shared.GameStates;
using Robust.Shared.Input.Binding;
Expand All @@ -28,108 +27,166 @@ public sealed class ActionsSystem : SharedActionsSystem
[Dependency] private readonly ISerializationManager _serialization = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;

public event Action<EntityUid>? ActionAdded;
public event Action<EntityUid>? ActionRemoved;
public event Action<EntityUid>? OnActionAdded;
public event Action<EntityUid>? OnActionRemoved;
public event OnActionReplaced? ActionReplaced;
public event Action? ActionsUpdated;
public event Action<ActionsComponent>? LinkActions;
public event Action? UnlinkActions;
public event Action? ClearAssignments;
public event Action<List<SlotAssignment>>? AssignSlot;

/// <summary>
/// Queue of entities with <see cref="ActionsComponent"/> that needs to be updated after
/// handling a state.
/// </summary>
private readonly Queue<EntityUid> _actionHoldersQueue = new();
private readonly List<EntityUid> _removed = new();
private readonly List<(EntityUid, BaseActionComponent?)> _added = new();

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ActionsComponent, PlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<ActionsComponent, PlayerDetachedEvent>(OnPlayerDetached);
SubscribeLocalEvent<ActionsComponent, ComponentHandleState>(HandleComponentState);

SubscribeLocalEvent<InstantActionComponent, ComponentHandleState>(OnInstantHandleState);
SubscribeLocalEvent<EntityTargetActionComponent, ComponentHandleState>(OnEntityTargetHandleState);
SubscribeLocalEvent<WorldTargetActionComponent, ComponentHandleState>(OnWorldTargetHandleState);
}

public override void Dirty(EntityUid? actionId)
private void OnInstantHandleState(EntityUid uid, InstantActionComponent component, ref ComponentHandleState args)
{
var action = GetActionData(actionId);
if (_playerManager.LocalPlayer?.ControlledEntity != action?.AttachedEntity)
if (args.Current is not InstantActionComponentState state)
return;

base.Dirty(actionId);
ActionsUpdated?.Invoke();
BaseHandleState<InstantActionComponent>(uid, component, state);
}

private void HandleComponentState(EntityUid uid, ActionsComponent component, ref ComponentHandleState args)
private void OnEntityTargetHandleState(EntityUid uid, EntityTargetActionComponent component, ref ComponentHandleState args)
{
if (args.Current is not ActionsComponentState state)
if (args.Current is not EntityTargetActionComponentState state)
return;

component.Actions.Clear();
component.Actions.UnionWith(EnsureEntitySet<ActionsComponent>(state.Actions, uid));
component.Whitelist = state.Whitelist;
component.CanTargetSelf = state.CanTargetSelf;
BaseHandleState<EntityTargetActionComponent>(uid, component, state);
}

_actionHoldersQueue.Enqueue(uid);
private void OnWorldTargetHandleState(EntityUid uid, WorldTargetActionComponent component, ref ComponentHandleState args)
{
if (args.Current is not WorldTargetActionComponentState state)
return;

BaseHandleState<WorldTargetActionComponent>(uid, component, state);
}

protected override void AddActionInternal(EntityUid holderId, EntityUid actionId, BaseContainer container, ActionsComponent holder)
private void BaseHandleState<T>(EntityUid uid, BaseActionComponent component, BaseActionComponentState state) where T : BaseActionComponent
{
// Sometimes the client receives actions from the server, before predicting that newly added components will add
// their own shared actions. Just in case those systems ever decided to directly access action properties (e.g.,
// action.Toggled), we will remove duplicates:
if (container.Contains(actionId))
{
ActionReplaced?.Invoke(actionId);
}
else
{
base.AddActionInternal(holderId, actionId, container, holder);
}
component.Icon = state.Icon;
component.IconOn = state.IconOn;
component.IconColor = state.IconColor;
component.Keywords = new HashSet<string>(state.Keywords);
component.Enabled = state.Enabled;
component.Toggled = state.Toggled;
component.Cooldown = state.Cooldown;
component.UseDelay = state.UseDelay;
component.Charges = state.Charges;
component.Container = EnsureEntity<T>(state.Container, uid);
component.EntityIcon = EnsureEntity<T>(state.EntityIcon, uid);
component.CheckCanInteract = state.CheckCanInteract;
component.ClientExclusive = state.ClientExclusive;
component.Priority = state.Priority;
component.AttachedEntity = EnsureEntity<T>(state.AttachedEntity, uid);
component.AutoPopulate = state.AutoPopulate;
component.Temporary = state.Temporary;
component.ItemIconStyle = state.ItemIconStyle;
component.Sound = state.Sound;

if (_playerManager.LocalPlayer?.ControlledEntity == component.AttachedEntity)
ActionsUpdated?.Invoke();
}

public override void AddAction(EntityUid holderId, EntityUid actionId, EntityUid? provider, ActionsComponent? holder = null, BaseActionComponent? action = null, bool dirty = true, BaseContainer? actionContainer = null)
protected override void UpdateAction(EntityUid? actionId, BaseActionComponent? action = null)
{
if (!Resolve(holderId, ref holder, false))
if (!ResolveActionData(actionId, ref action))
return;

action ??= GetActionData(actionId);
if (action == null)
{
Log.Warning($"No {nameof(BaseActionComponent)} found on entity {actionId}");
base.UpdateAction(actionId, action);
if (_playerManager.LocalPlayer?.ControlledEntity != action.AttachedEntity)
return;
}

dirty &= !action.ClientExclusive;
base.AddAction(holderId, actionId, provider, holder, action, dirty, actionContainer);

if (holderId == _playerManager.LocalPlayer?.ControlledEntity)
ActionAdded?.Invoke(actionId);
ActionsUpdated?.Invoke();
}

public override void RemoveAction(EntityUid holderId, EntityUid? actionId, ActionsComponent? comp = null, BaseActionComponent? action = null, bool dirty = true)
private void HandleComponentState(EntityUid uid, ActionsComponent component, ref ComponentHandleState args)
{
if (GameTiming.ApplyingState)
if (args.Current is not ActionsComponentState state)
return;

if (!Resolve(holderId, ref comp, false))
return;
_added.Clear();
_removed.Clear();
var stateEnts = EnsureEntitySet<ActionsComponent>(state.Actions, uid);
foreach (var act in component.Actions)
{
if (!stateEnts.Contains(act) && !IsClientSide(act))
_removed.Add(act);
}
component.Actions.ExceptWith(_removed);

foreach (var actionId in stateEnts)
{
if (!actionId.IsValid())
continue;

if (actionId == null)
if (!component.Actions.Add(actionId))
continue;

TryGetActionData(actionId, out var action);
_added.Add((actionId, action));
}

if (_playerManager.LocalPlayer?.ControlledEntity != uid)
return;

action ??= GetActionData(actionId);
foreach (var action in _removed)
{
OnActionRemoved?.Invoke(action);
}

_added.Sort(ActionComparer);

foreach (var action in _added)
{
OnActionAdded?.Invoke(action.Item1);
}

ActionsUpdated?.Invoke();
}

public static int ActionComparer((EntityUid, BaseActionComponent?) a, (EntityUid, BaseActionComponent?) b)
{
var priorityA = a.Item2?.Priority ?? 0;
var priorityB = b.Item2?.Priority ?? 0;
if (priorityA != priorityB)
return priorityA - priorityB;

priorityA = a.Item2?.Container?.Id ?? 0;
priorityB = b.Item2?.Container?.Id ?? 0;
return priorityA - priorityB;
}

if (action is { ClientExclusive: false })
protected override void ActionAdded(EntityUid performer, EntityUid actionId, ActionsComponent comp,
BaseActionComponent action)
{
if (_playerManager.LocalPlayer?.ControlledEntity != performer)
return;

dirty &= !action?.ClientExclusive ?? true;
base.RemoveAction(holderId, actionId, comp, action, dirty);
OnActionAdded?.Invoke(actionId);
}

if (_playerManager.LocalPlayer?.ControlledEntity != holderId)
protected override void ActionRemoved(EntityUid performer, EntityUid actionId, ActionsComponent comp, BaseActionComponent action)
{
if (_playerManager.LocalPlayer?.ControlledEntity != performer)
return;

if (action == null || action.AutoRemove)
ActionRemoved?.Invoke(actionId.Value);
OnActionRemoved?.Invoke(actionId);
}

public IEnumerable<(EntityUid Id, BaseActionComponent Comp)> GetClientActions()
Expand Down Expand Up @@ -180,9 +237,6 @@ public void TriggerAction(EntityUid actionId, BaseActionComponent action)
return;
}

if (action.Provider != null && Deleted(action.Provider))
return;

if (action is not InstantActionComponent instantAction)
return;

Expand Down Expand Up @@ -233,8 +287,8 @@ public void LoadActionAssignments(string path, bool userData)

var action = _serialization.Read<BaseActionComponent>(actionNode, notNullableOverride: true);
var actionId = Spawn(null);
AddComp<Component>(actionId, action);
AddAction(user, actionId, null);
AddComp(actionId, action);
AddActionDirect(user, actionId);

if (map.TryGet<ValueDataNode>("name", out var nameNode))
_metaData.SetEntityName(actionId, nameNode.Value);
Expand All @@ -254,95 +308,6 @@ public void LoadActionAssignments(string path, bool userData)
AssignSlot?.Invoke(assignments);
}

public override void Update(float frameTime)
{
base.Update(frameTime);

if (_actionHoldersQueue.Count == 0)
return;

var removed = new List<EntityUid>();
var added = new List<(EntityUid Id, BaseActionComponent Comp)>();
var query = GetEntityQuery<ActionsComponent>();
var queue = new Queue<EntityUid>(_actionHoldersQueue);
_actionHoldersQueue.Clear();

while (queue.TryDequeue(out var holderId))
{
if (!TryGetContainer(holderId, out var container) || container.ExpectedEntities.Count > 0)
{
_actionHoldersQueue.Enqueue(holderId);
continue;
}

if (!query.TryGetComponent(holderId, out var holder))
continue;

removed.Clear();
added.Clear();

foreach (var (act, data) in holder.OldClientActions.ToList())
{
if (data.ClientExclusive)
continue;

if (!holder.Actions.Contains(act))
{
holder.OldClientActions.Remove(act);
if (data.AutoRemove)
removed.Add(act);
}
}

// Anything that remains is a new action
foreach (var newAct in holder.Actions)
{
if (!TryGetActionData(newAct, out var serverData))
continue;

if (!holder.OldClientActions.ContainsKey(newAct))
added.Add((newAct, serverData));

holder.OldClientActions[newAct] = new ActionMetaData(serverData.ClientExclusive, serverData.AutoRemove);
}

if (_playerManager.LocalPlayer?.ControlledEntity != holderId)
return;

foreach (var action in removed)
{
ActionRemoved?.Invoke(action);
}

added.Sort(static (a, b) =>
{
if (a.Comp.Priority != b.Comp.Priority)
return a.Comp.Priority - b.Comp.Priority;

if (a.Comp.Provider != b.Comp.Provider)
{
if (a.Comp.Provider == null)
return -1;

if (b.Comp.Provider == null)
return 1;

// uid to int casting... it says "Do NOT use this in content". You can't tell me what to do.
return (int) a.Comp.Provider - (int) b.Comp.Provider;
}

return 0;
});

foreach (var action in added)
{
ActionAdded?.Invoke(action.Item1);
}

ActionsUpdated?.Invoke();
}
}

public record struct SlotAssignment(byte Hotbar, byte Slot, EntityUid ActionId);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
<ui:FancyWindow xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
VerticalExpand="True" HorizontalExpand="True"
Title="{Loc admin-notes-message-window-title}"
MinSize="600 170">
<PanelContainer VerticalExpand="True" HorizontalExpand="True">
<PanelContainer.PanelOverride>
<graphics:StyleBoxFlat BackgroundColor="#25252A" />
</PanelContainer.PanelOverride>
<PanelContainer VerticalExpand="True" HorizontalExpand="True" StyleClasses="BackgroundDark">
<ScrollContainer HScrollEnabled="False" VerticalExpand="True" HorizontalExpand="True" Margin="4">
<BoxContainer Orientation="Vertical" SeparationOverride="10" VerticalAlignment="Bottom">
<Label Name="AdminLabel" Text="Loading..." />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
<ui:FancyWindow xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
VerticalExpand="True" HorizontalExpand="True"
Title="{Loc admin-remarks-title}"
SetSize="600 400">
<PanelContainer>
<PanelContainer.PanelOverride>
<graphics:StyleBoxFlat BackgroundColor="#25252A" />
</PanelContainer.PanelOverride>
<PanelContainer StyleClasses="BackgroundDark">
<BoxContainer Orientation="Vertical" Margin="4">
<ScrollContainer VerticalExpand="True" HorizontalExpand="True" HScrollEnabled="False">
<BoxContainer Orientation="Vertical" Name="NotesContainer" Access="Public" VerticalExpand="True" />
Expand Down
Loading

0 comments on commit 1ab1b11

Please sign in to comment.