more component ref removal + combining server/client comps (#13178)

Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
This commit is contained in:
Nemanja
2022-12-24 23:28:21 -05:00
committed by GitHub
parent fddcc0cece
commit faca40b8d5
78 changed files with 504 additions and 643 deletions

View File

@@ -1,9 +1,7 @@
using Content.Shared.Flash;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Timing;
namespace Content.Client.Flash

View File

@@ -1,12 +0,0 @@
using Content.Shared.Flash;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
namespace Content.Client.Flash
{
[ComponentReference(typeof(SharedFlashableComponent))]
[RegisterComponent, Access(typeof(FlashSystem))]
public sealed class FlashableComponent : SharedFlashableComponent
{
}
}

View File

@@ -1,15 +0,0 @@
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Humanoid.Prototypes;
namespace Content.Client.Humanoid;
[RegisterComponent]
public sealed class HumanoidComponent : SharedHumanoidComponent
{
[ViewVariables] public List<Marking> CurrentMarkings = new();
public Dictionary<HumanoidVisualLayers, HumanoidSpeciesSpriteLayer> BaseLayers = new();
public string LastSpecies = default!;
}

View File

@@ -108,23 +108,23 @@ public sealed class HumanoidVisualizerSystem : VisualizerSystem<HumanoidComponen
SpriteComponent sprite)
{
// skip this entire thing if both sets are empty
if (humanoid.CurrentMarkings.Count == 0 && newMarkings.Count == 0)
if (humanoid.CurrentClientMarkings.Count == 0 && newMarkings.Count == 0)
{
return;
}
var dirtyMarkings = new List<int>();
var dirtyRangeStart = humanoid.CurrentMarkings.Count == 0 ? 0 : -1;
var dirtyRangeStart = humanoid.CurrentClientMarkings.Count == 0 ? 0 : -1;
// edge cases:
// humanoid.CurrentMarkings < newMarkings.Count
// humanoid.CurrentClientMarkings < newMarkings.Count
// - check if count matches this condition before diffing
// - if count is unequal, set dirty range to start from humanoid.CurrentMarkings.Count
// humanoid.CurrentMarkings > newMarkings.Count, no dirty markings
// - if count is unequal, set dirty range to start from humanoid.CurrentClientMarkings.Count
// humanoid.CurrentClientMarkings > newMarkings.Count, no dirty markings
// - break count upon meeting this condition
// - clear markings from newMarkings.Count to humanoid.CurrentMarkings.Count - newMarkings.Count
// - clear markings from newMarkings.Count to humanoid.CurrentClientMarkings.Count - newMarkings.Count
for (var i = 0; i < humanoid.CurrentMarkings.Count; i++)
for (var i = 0; i < humanoid.CurrentClientMarkings.Count; i++)
{
// if we've reached the end of the new set of markings,
// then that means it's time to finish
@@ -135,7 +135,7 @@ public sealed class HumanoidVisualizerSystem : VisualizerSystem<HumanoidComponen
// if the marking is different here, set the range start to i and break, we need
// to rebuild all markings starting from i
if (humanoid.CurrentMarkings[i].MarkingId != newMarkings[i].MarkingId)
if (humanoid.CurrentClientMarkings[i].MarkingId != newMarkings[i].MarkingId)
{
dirtyRangeStart = i;
break;
@@ -146,7 +146,7 @@ public sealed class HumanoidVisualizerSystem : VisualizerSystem<HumanoidComponen
// however: if the hidden layers are set to dirty, then we need to
// instead just add every single marking, since we don't know ahead of time
// where these markings go
if (humanoid.CurrentMarkings[i] != newMarkings[i] || layersDirty)
if (humanoid.CurrentClientMarkings[i] != newMarkings[i] || layersDirty)
{
dirtyMarkings.Add(i);
}
@@ -162,49 +162,49 @@ public sealed class HumanoidVisualizerSystem : VisualizerSystem<HumanoidComponen
ApplyMarking(uid, dirtyMarking, newMarkings[i].MarkingColors, newMarkings[i].Visible, humanoid, sprite);
}
if (humanoid.CurrentMarkings.Count < newMarkings.Count && dirtyRangeStart < 0)
if (humanoid.CurrentClientMarkings.Count < newMarkings.Count && dirtyRangeStart < 0)
{
dirtyRangeStart = humanoid.CurrentMarkings.Count;
dirtyRangeStart = humanoid.CurrentClientMarkings.Count;
}
if (dirtyRangeStart >= 0)
{
var range = newMarkings.GetRange(dirtyRangeStart, newMarkings.Count - dirtyRangeStart);
if (humanoid.CurrentMarkings.Count > 0)
if (humanoid.CurrentClientMarkings.Count > 0)
{
var oldRange = humanoid.CurrentMarkings.GetRange(dirtyRangeStart, humanoid.CurrentMarkings.Count - dirtyRangeStart);
var oldRange = humanoid.CurrentClientMarkings.GetRange(dirtyRangeStart, humanoid.CurrentClientMarkings.Count - dirtyRangeStart);
ClearMarkings(uid, oldRange, humanoid, sprite);
}
ApplyMarkings(uid, range, humanoid, sprite);
}
else if (humanoid.CurrentMarkings.Count != newMarkings.Count)
else if (humanoid.CurrentClientMarkings.Count != newMarkings.Count)
{
if (newMarkings.Count == 0)
{
ClearAllMarkings(uid, humanoid, sprite);
}
else if (humanoid.CurrentMarkings.Count > newMarkings.Count)
else if (humanoid.CurrentClientMarkings.Count > newMarkings.Count)
{
var rangeStart = newMarkings.Count;
var rangeCount = humanoid.CurrentMarkings.Count - newMarkings.Count;
var range = humanoid.CurrentMarkings.GetRange(rangeStart, rangeCount);
var rangeCount = humanoid.CurrentClientMarkings.Count - newMarkings.Count;
var range = humanoid.CurrentClientMarkings.GetRange(rangeStart, rangeCount);
ClearMarkings(uid, range, humanoid, sprite);
}
}
if (dirtyMarkings.Count > 0 || dirtyRangeStart >= 0 || humanoid.CurrentMarkings.Count != newMarkings.Count)
if (dirtyMarkings.Count > 0 || dirtyRangeStart >= 0 || humanoid.CurrentClientMarkings.Count != newMarkings.Count)
{
humanoid.CurrentMarkings = newMarkings;
humanoid.CurrentClientMarkings = newMarkings;
}
}
private void ClearAllMarkings(EntityUid uid, HumanoidComponent humanoid,
SpriteComponent spriteComp)
{
ClearMarkings(uid, humanoid.CurrentMarkings, humanoid, spriteComp);
ClearMarkings(uid, humanoid.CurrentClientMarkings, humanoid, spriteComp);
}
private void ClearMarkings(EntityUid uid, List<Marking> markings, HumanoidComponent humanoid,

View File

@@ -1,8 +0,0 @@
using Content.Shared.Projectiles;
namespace Content.Client.Projectiles
{
[RegisterComponent]
[ComponentReference(typeof(SharedProjectileComponent))]
public sealed class ProjectileComponent : SharedProjectileComponent {}
}

View File

@@ -1,13 +0,0 @@
using Content.Shared.Singularity.Components;
using Content.Client.Singularity.EntitySystems;
namespace Content.Client.Singularity.Components;
/// <summary>
/// The client-side version of <see cref="SharedSingularityComponent"/>.
/// Primarily managed by <see cref="SingularitySystem"/>.
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(SharedSingularityComponent))]
public sealed class SingularityComponent : SharedSingularityComponent
{}

View File

@@ -14,7 +14,7 @@ public sealed class SingularitySystem : SharedSingularitySystem
{
base.Initialize();
SubscribeLocalEvent<SharedSingularityComponent, ComponentHandleState>(HandleSingularityState);
SubscribeLocalEvent<SingularityComponent, ComponentHandleState>(HandleSingularityState);
}
/// <summary>
@@ -23,7 +23,7 @@ public sealed class SingularitySystem : SharedSingularitySystem
/// <param name="uid">The uid of the singularity to sync.</param>
/// <param name="comp">The state of the singularity to sync.</param>
/// <param name="args">The event arguments including the state to sync the singularity with.</param>
private void HandleSingularityState(EntityUid uid, SharedSingularityComponent comp, ref ComponentHandleState args)
private void HandleSingularityState(EntityUid uid, SingularityComponent comp, ref ComponentHandleState args)
{
if (args.Current is not SingularityComponentState state)
return;

View File

@@ -1,18 +0,0 @@
using Content.Client.Items.Components;
using Content.Client.Message;
using Content.Client.Stylesheets;
using Content.Shared.Stacks;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;
namespace Content.Client.Stack
{
[RegisterComponent, Access(typeof(StackSystem), typeof(StackStatusControl))]
[ComponentReference(typeof(SharedStackComponent))]
public sealed class StackComponent : SharedStackComponent
{
[ViewVariables]
public bool UiUpdateNeeded { get; set; }
}
}

View File

@@ -1,5 +1,6 @@
using Content.Client.Message;
using Content.Client.Stylesheets;
using Content.Shared.Stacks;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;

View File

@@ -18,7 +18,7 @@ namespace Content.Client.Stack
args.Controls.Add(new StackStatusControl(component));
}
public override void SetCount(EntityUid uid, int amount, SharedStackComponent? component = null)
public override void SetCount(EntityUid uid, int amount, StackComponent? component = null)
{
if (!Resolve(uid, ref component))
return;

View File

@@ -7,17 +7,6 @@ using Robust.Shared.Timing;
namespace Content.Client.Tools.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedMultipleToolComponent))]
public sealed class MultipleToolComponent : SharedMultipleToolComponent
{
[ViewVariables(VVAccess.ReadWrite)]
public bool UiUpdateNeeded;
[DataField("statusShowBehavior")]
public bool StatusShowBehavior = true;
}
public sealed class MultipleToolStatusControl : Control
{
private readonly MultipleToolComponent _parent;

View File

@@ -20,7 +20,7 @@ namespace Content.Client.Tools
}
public override void SetMultipleTool(EntityUid uid,
SharedMultipleToolComponent? multiple = null,
MultipleToolComponent? multiple = null,
ToolComponent? tool = null,
bool playSound = false,
EntityUid? user = null)
@@ -29,7 +29,7 @@ namespace Content.Client.Tools
return;
base.SetMultipleTool(uid, multiple, tool, playSound, user);
((MultipleToolComponent)multiple).UiUpdateNeeded = true;
multiple.UiUpdateNeeded = true;
// TODO replace this with appearance + visualizer
// in order to convert this to a specifier, the manner in which the sprite is specified in yaml needs to be updated.

View File

@@ -1,60 +0,0 @@
using Content.Shared.VendingMachines;
namespace Content.Client.VendingMachines;
[RegisterComponent]
[ComponentReference(typeof(SharedVendingMachineComponent))]
[Access(typeof(VendingMachineSystem))]
public sealed class VendingMachineComponent : SharedVendingMachineComponent
{
/// <summary>
/// RSI state for when the vending machine is unpowered.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Base"/>
/// </summary>
[DataField("offState")]
public string? OffState;
/// <summary>
/// RSI state for the screen of the vending machine
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Screen"/>
/// </summary>
[DataField("screenState")]
public string? ScreenState;
/// <summary>
/// RSI state for the vending machine's normal state. Usually a looping animation.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
/// </summary>
[DataField("normalState")]
public string? NormalState;
/// <summary>
/// RSI state for the vending machine's eject animation.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
/// </summary>
[DataField("ejectState")]
public string? EjectState;
/// <summary>
/// RSI state for the vending machine's deny animation. Will either be played once as sprite flick
/// or looped depending on how <see cref="LoopDenyAnimation"/> is set.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
/// </summary>
[DataField("denyState")]
public string? DenyState;
/// <summary>
/// RSI state for when the vending machine is unpowered.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Base"/>
/// </summary>
[DataField("brokenState")]
public string? BrokenState;
/// <summary>
/// If set to <c>true</c> (default) will loop the animation of the <see cref="DenyState"/> for the duration
/// of <see cref="SharedVendingMachineComponent.DenyDelay"/>. If set to <c>false</c> will play a sprite
/// flick animation for the state and then linger on the final frame until the end of the delay.
/// </summary>
[DataField("loopDeny")]
public bool LoopDenyAnimation = true;
}

View File

@@ -137,19 +137,3 @@ public sealed class VendingMachineSystem : SharedVendingMachineSystem
sprite.LayerSetVisible(actualLayer, false);
}
}
public enum VendingMachineVisualLayers : byte
{
/// <summary>
/// Off / Broken. The other layers will overlay this if the machine is on.
/// </summary>
Base,
/// <summary>
/// Normal / Deny / Eject
/// </summary>
BaseUnshaded,
/// <summary>
/// Screens that are persistent (where the machine is not off or broken)
/// </summary>
Screen
}

View File

@@ -1,9 +1,7 @@
using Content.Client.Projectiles;
using Content.Shared.Projectiles;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Systems;
using Robust.Client.Player;
using Robust.Shared.Audio;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Physics.Events;
using Robust.Shared.Player;
using Robust.Shared.Random;

View File

@@ -25,6 +25,7 @@ using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.Inventory;
using Content.Shared.PDA;
using Content.Shared.Stacks;
using Content.Shared.Verbs;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Server.GameObjects;

View File

@@ -3,6 +3,7 @@ using Content.Server.Chat;
using Content.Server.Chat.Systems;
using Content.Server.Power.Components;
using Content.Server.VendingMachines;
using Content.Shared.VendingMachines;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;

View File

@@ -10,6 +10,7 @@ using Content.Shared.Body.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Materials;
using Content.Shared.MobState.Components;
using Content.Shared.Stacks;
using Robust.Shared.Console;
using Robust.Shared.Containers;
using Robust.Shared.Map;

View File

@@ -22,6 +22,7 @@ using Content.Server.Construction.Components;
using Content.Server.Materials;
using Content.Server.Stack;
using Content.Server.Jobs;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Prototypes;
using Robust.Server.GameObjects;
using Robust.Server.Containers;

View File

@@ -2,6 +2,7 @@ using Content.Server.Stack;
using Content.Shared.Construction;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Prototypes;
using Content.Shared.Stacks;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;

View File

@@ -1,6 +1,7 @@
using Content.Server.Stack;
using Content.Shared.Construction;
using Content.Shared.Prototypes;
using Content.Shared.Stacks;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;

View File

@@ -3,6 +3,7 @@ using Content.Server.Stack;
using Content.Shared.Construction;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Stacks;
using Content.Shared.Tag;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;

View File

@@ -2,6 +2,7 @@ using Content.Server.Construction.Components;
using Content.Server.Tools;
using Content.Server.Stack;
using Content.Shared.Interaction;
using Content.Shared.Stacks;
using Content.Shared.Tools.Components;
namespace Content.Server.Construction

View File

@@ -1,4 +1,5 @@
using Content.Server.VendingMachines;
using Content.Shared.VendingMachines;
namespace Content.Server.Destructible.Thresholds.Behaviors
{

View File

@@ -1,5 +1,6 @@
using Content.Server.Stack;
using Content.Shared.Prototypes;
using Content.Shared.Stacks;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;

View File

@@ -11,7 +11,6 @@ using System.Threading;
using Content.Server.Chat.Systems;
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
using Content.Server.Humanoid;
using Content.Server.NPC;
using Content.Shared.Damage;
using Content.Shared.Dragon;
@@ -22,6 +21,7 @@ using Robust.Shared.GameStates;
using Robust.Shared.Map;
using Robust.Shared.Random;
using Content.Server.NPC.Systems;
using Content.Shared.Humanoid;
namespace Content.Server.Dragon
{

View File

@@ -60,7 +60,7 @@ namespace Content.Server.Engineering.EntitySystems
if (component.Deleted || Deleted(component.Owner))
return;
if (EntityManager.TryGetComponent<SharedStackComponent?>(component.Owner, out var stackComp)
if (EntityManager.TryGetComponent<StackComponent?>(component.Owner, out var stackComp)
&& component.RemoveOnInteract && !_stackSystem.Use(uid, 1, stackComp))
{
return;

View File

@@ -1,10 +0,0 @@
using Content.Shared.Flash;
namespace Content.Server.Flash.Components
{
[ComponentReference(typeof(SharedFlashableComponent))]
[RegisterComponent, Access(typeof(FlashSystem))]
public sealed class FlashableComponent : SharedFlashableComponent
{
}
}

View File

@@ -3,7 +3,6 @@ using Content.Server.Actions;
using Content.Server.Chat.Managers;
using Content.Server.Disease;
using Content.Server.Disease.Components;
using Content.Server.Humanoid;
using Content.Server.Mind.Components;
using Content.Server.MobState;
using Content.Server.Players;
@@ -14,6 +13,7 @@ using Content.Server.Traitor;
using Content.Server.Zombies;
using Content.Shared.Actions.ActionTypes;
using Content.Shared.CCVar;
using Content.Shared.Humanoid;
using Content.Shared.MobState;
using Content.Shared.MobState.Components;
using Content.Shared.Preferences;
@@ -21,7 +21,6 @@ using Content.Shared.Roles;
using Content.Shared.Zombies;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;

View File

@@ -15,6 +15,7 @@ using Content.Shared.Input;
using Content.Shared.Inventory;
using Content.Shared.Physics.Pull;
using Content.Shared.Pulling.Components;
using Content.Shared.Stacks;
using Content.Shared.Throwing;
using JetBrains.Annotations;
using Robust.Server.Player;

View File

@@ -1,38 +0,0 @@
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Preferences;
using Robust.Shared.Enums;
namespace Content.Server.Humanoid;
[RegisterComponent]
public sealed class HumanoidComponent : SharedHumanoidComponent
{
public MarkingSet CurrentMarkings = new();
/// <summary>
/// Any custom base layers this humanoid might have. See:
/// limb transplants (potentially), robotic arms, etc.
/// Stored on the server, this is merged in the client into
/// all layer settings.
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
public Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> CustomBaseLayers = new();
public HashSet<HumanoidVisualLayers> PermanentlyHidden = new();
public HashSet<HumanoidVisualLayers> AllHiddenLayers
{
get
{
var result = new HashSet<HumanoidVisualLayers>(HiddenLayers);
result.UnionWith(PermanentlyHidden);
return result;
}
}
// Couldn't these be somewhere else?
[ViewVariables] public Gender Gender = default!;
[ViewVariables] public int Age = 18;
}

View File

@@ -1,4 +1,5 @@
using Content.Server.CharacterAppearance.Components;
using Content.Shared.Humanoid;
using Content.Shared.Preferences;
namespace Content.Server.Humanoid.Systems;

View File

@@ -1,13 +1,12 @@
using Content.Server.Access.Systems;
using Content.Server.Administration.Logs;
using Content.Server.Humanoid;
using Content.Shared.Database;
using Content.Shared.Hands;
using Content.Shared.Humanoid;
using Content.Shared.IdentityManagement;
using Content.Shared.IdentityManagement.Components;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Content.Shared.Preferences;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects.Components.Localization;

View File

@@ -12,6 +12,7 @@ using Content.Shared.Interaction;
using Content.Shared.Kitchen;
using Content.Shared.Popups;
using Content.Shared.Random.Helpers;
using Content.Shared.Stacks;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;

View File

@@ -1,6 +1,7 @@
using System.Linq;
using Content.Server.Humanoid;
using Content.Server.UserInterface;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.MagicMirror;
using Robust.Server.GameObjects;

View File

@@ -17,12 +17,11 @@ using Content.Server.Body.Components;
using Content.Server.Climbing;
using Content.Server.Construction;
using Content.Server.DoAfter;
using Content.Server.Humanoid;
using Content.Server.Mind.Components;
using Content.Server.Stack;
using Content.Shared.Humanoid;
using Content.Shared.Interaction.Events;
using Content.Shared.Popups;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Configuration;
using Robust.Server.Player;

View File

@@ -123,7 +123,7 @@ public sealed class HealingSystem : EntitySystem
return false;
}
if (TryComp<SharedStackComponent>(component.Owner, out var stack) && stack.Count < 1)
if (TryComp<StackComponent>(component.Owner, out var stack) && stack.Count < 1)
return false;
component.CancelToken = new CancellationTokenSource();

View File

@@ -1,6 +1,6 @@
using Content.Server.Projectiles;
using Content.Server.Projectiles.Components;
using Content.Server.Singularity.Components;
using Content.Shared.Projectiles;
using Content.Shared.Singularity.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Timing;

View File

@@ -2,6 +2,7 @@ using Content.Server.Power.Components;
using Content.Server.Stack;
using Content.Shared.Interaction;
using Content.Shared.Maps;
using Content.Shared.Stacks;
using Robust.Shared.Map;
namespace Content.Server.Power.EntitySystems;

View File

@@ -1,29 +0,0 @@
using Content.Shared.Damage;
using Content.Shared.Projectiles;
using Robust.Shared.Audio;
namespace Content.Server.Projectiles.Components
{
[RegisterComponent]
[ComponentReference(typeof(SharedProjectileComponent))]
public sealed class ProjectileComponent : SharedProjectileComponent
{
[DataField("damage", required: true)]
[ViewVariables(VVAccess.ReadWrite)]
public DamageSpecifier Damage = default!;
[DataField("deleteOnCollide")]
public bool DeleteOnCollide { get; } = true;
[DataField("ignoreResistances")]
public bool IgnoreResistances { get; } = false;
// Get that juicy FPS hit sound
[DataField("soundHit")] public SoundSpecifier? SoundHit;
[DataField("soundForce")]
public bool ForceSound = false;
public bool DamagedEntity;
}
}

View File

@@ -1,5 +1,4 @@
using Content.Server.Administration.Logs;
using Content.Server.Projectiles.Components;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Camera;
using Content.Shared.Damage;

View File

@@ -27,6 +27,7 @@ using Content.Server.Humanoid;
using Content.Server.Revenant.Components;
using Content.Server.Store.Components;
using Content.Shared.FixedPoint;
using Content.Shared.Humanoid;
using Content.Shared.Revenant.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Utility;

View File

@@ -4,19 +4,18 @@ using Content.Server.Construction;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Projectiles;
using Content.Server.Projectiles.Components;
using Content.Server.Singularity.Components;
using Content.Server.Storage.Components;
using Content.Shared.Database;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.Projectiles;
using Content.Shared.Singularity.Components;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Utility;
using Timer = Robust.Shared.Timing.Timer;

View File

@@ -14,9 +14,9 @@ using Content.Server.Singularity.Events;
namespace Content.Server.Singularity.EntitySystems;
/// <summary>
/// The server-side version of <seed cref="SharedSingularitySystem">.
/// The server-side version of <see cref="SharedSingularitySystem"/>.
/// Primarily responsible for managing <see cref="SingularityComponent"/>s.
/// Handles their accumulation of energy upon consuming entities (see <see cref="EventHorizonComponent">) and gradual dissipation.
/// Handles their accumulation of energy upon consuming entities (see <see cref="EventHorizonComponent"/>) and gradual dissipation.
/// Also handles synchronizing server-side components with the singuarities level.
/// </summary>
public sealed class SingularitySystem : SharedSingularitySystem
@@ -41,7 +41,6 @@ public sealed class SingularitySystem : SharedSingularitySystem
{
base.Initialize();
SubscribeLocalEvent<SingularityDistortionComponent, ComponentStartup>(OnDistortionStartup);
SubscribeLocalEvent<SingularityComponent, ComponentStartup>(OnSingularityStartup);
SubscribeLocalEvent<SingularityComponent, ComponentShutdown>(OnSingularityShutdown);
SubscribeLocalEvent<SingularityComponent, EventHorizonConsumedEntityEvent>(OnConsumed);
SubscribeLocalEvent<SinguloFoodComponent, EventHorizonConsumedEntityEvent>(OnConsumed);
@@ -198,7 +197,7 @@ public sealed class SingularitySystem : SharedSingularitySystem
/// <param name="uid">The entity UID of the singularity that is forming.</param>
/// <param name="comp">The component of the singularity that is forming.</param>
/// <param name="args">The event arguments.</param>
public void OnSingularityStartup(EntityUid uid, SingularityComponent comp, ComponentStartup args)
protected override void OnSingularityStartup(EntityUid uid, SingularityComponent comp, ComponentStartup args)
{
comp.LastUpdateTime = _timing.CurTime;
comp.NextUpdateTime = comp.LastUpdateTime + comp.TargetUpdatePeriod;
@@ -309,7 +308,8 @@ public sealed class SingularitySystem : SharedSingularitySystem
/// <param name="args">The event arguments.</param>
public void UpdateEnergyDrain(EntityUid uid, SingularityComponent comp, SingularityLevelChangedEvent args)
{
comp.EnergyDrain = args.NewValue switch {
comp.EnergyDrain = args.NewValue switch
{
6 => 20,
5 => 15,
4 => 10,

View File

@@ -1,13 +0,0 @@
using Content.Shared.Stacks;
namespace Content.Server.Stack
{
// TODO: Naming and presentation and such could use some improvement.
[RegisterComponent, Access(typeof(StackSystem))]
[ComponentReference(typeof(SharedStackComponent))]
public sealed class StackComponent : SharedStackComponent
{
[ViewVariables(VVAccess.ReadWrite)]
public bool ThrowIndividually { get; set; } = false;
}
}

View File

@@ -26,7 +26,7 @@ namespace Content.Server.Stack
SubscribeLocalEvent<StackComponent, GetVerbsEvent<AlternativeVerb>>(OnStackAlternativeInteract);
}
public override void SetCount(EntityUid uid, int amount, SharedStackComponent? component = null)
public override void SetCount(EntityUid uid, int amount, StackComponent? component = null)
{
if (!Resolve(uid, ref component, false))
return;
@@ -41,7 +41,7 @@ namespace Content.Server.Stack
/// <summary>
/// Try to split this stack into two. Returns a non-null <see cref="Robust.Shared.GameObjects.EntityUid"/> if successful.
/// </summary>
public EntityUid? Split(EntityUid uid, int amount, EntityCoordinates spawnPosition, SharedStackComponent? stack = null)
public EntityUid? Split(EntityUid uid, int amount, EntityCoordinates spawnPosition, StackComponent? stack = null)
{
if (!Resolve(uid, ref stack))
return null;
@@ -61,7 +61,7 @@ namespace Content.Server.Stack
// Set the output parameter in the event instance to the newly split stack.
var entity = Spawn(prototype, spawnPosition);
if (TryComp(entity, out SharedStackComponent? stackComp))
if (TryComp(entity, out StackComponent? stackComp))
{
// Set the split stack's count.
SetCount(entity, amount, stackComp);

View File

@@ -1,4 +1,5 @@
using Content.Server.Humanoid;
using Content.Shared.Humanoid;
using Content.Shared.Store;
using Content.Shared.Humanoid.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;

View File

@@ -8,6 +8,7 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Server.UserInterface;
using Content.Shared.Stacks;
namespace Content.Server.Store.Systems;

View File

@@ -3,6 +3,7 @@ using Content.Shared.Audio;
using Content.Shared.Interaction;
using Content.Shared.Maps;
using Content.Shared.Physics;
using Content.Shared.Stacks;
using Robust.Shared.Audio;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;

View File

@@ -1,9 +0,0 @@
using Content.Shared.Tools.Components;
namespace Content.Server.Tools.Components;
[RegisterComponent]
[ComponentReference(typeof(SharedMultipleToolComponent))]
public sealed class MultipleToolComponent : SharedMultipleToolComponent
{
}

View File

@@ -1,80 +0,0 @@
using Content.Shared.Actions.ActionTypes;
using Content.Shared.VendingMachines;
using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.VendingMachines
{
[RegisterComponent]
[ComponentReference(typeof(SharedVendingMachineComponent))]
[Access(typeof(VendingMachineSystem))]
public sealed class VendingMachineComponent : SharedVendingMachineComponent
{
public bool Ejecting;
public bool Denying;
public bool DispenseOnHitCoolingDown;
public string? NextItemToEject;
public bool Broken;
/// <summary>
/// When true, will forcefully throw any object it dispenses
/// </summary>
[DataField("speedLimiter")]
public bool CanShoot = false;
public bool ThrowNextItem = false;
/// <summary>
/// The chance that a vending machine will randomly dispense an item on hit.
/// Chance is 0 if null.
/// </summary>
[DataField("dispenseOnHitChance")]
public float? DispenseOnHitChance;
/// <summary>
/// The minimum amount of damage that must be done per hit to have a chance
/// of dispensing an item.
/// </summary>
[DataField("dispenseOnHitThreshold")]
public float? DispenseOnHitThreshold;
/// <summary>
/// Amount of time in seconds that need to pass before damage can cause a vending machine to eject again.
/// This value is separate to <see cref="SharedVendingMachineComponent.EjectDelay"/> because that value might be
/// 0 for a vending machine for legitimate reasons (no desired delay/no eject animation)
/// and can be circumvented with forced ejections.
/// </summary>
[DataField("dispenseOnHitCooldown")]
public float? DispenseOnHitCooldown = 1.0f;
/// <summary>
/// Sound that plays when ejecting an item
/// </summary>
[DataField("soundVend")]
// Grabbed from: https://github.com/discordia-space/CEV-Eris/blob/f702afa271136d093ddeb415423240a2ceb212f0/sound/machines/vending_drop.ogg
public SoundSpecifier SoundVend = new SoundPathSpecifier("/Audio/Machines/machine_vend.ogg");
/// <summary>
/// Sound that plays when an item can't be ejected
/// </summary>
[DataField("soundDeny")]
// Yoinked from: https://github.com/discordia-space/CEV-Eris/blob/35bbad6764b14e15c03a816e3e89aa1751660ba9/sound/machines/Custom_deny.ogg
public SoundSpecifier SoundDeny = new SoundPathSpecifier("/Audio/Machines/custom_deny.ogg");
/// <summary>
/// The action available to the player controlling the vending machine
/// </summary>
[DataField("action", customTypeSerializer: typeof(PrototypeIdSerializer<InstantActionPrototype>))]
public string? Action = "VendingThrow";
public float NonLimitedEjectForce = 7.5f;
public float NonLimitedEjectRange = 5f;
public float EjectAccumulator = 0f;
public float DenyAccumulator = 0f;
public float DispenseOnHitAccumulator = 0f;
}
}

View File

@@ -14,7 +14,6 @@ using Content.Shared.Throwing;
using Content.Shared.VendingMachines;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
@@ -72,11 +71,9 @@ namespace Content.Server.VendingMachines
args.Price += price;
}
protected override void OnComponentInit(EntityUid uid, SharedVendingMachineComponent sharedComponent, ComponentInit args)
protected override void OnComponentInit(EntityUid uid, VendingMachineComponent component, ComponentInit args)
{
base.OnComponentInit(uid, sharedComponent, args);
var component = (VendingMachineComponent) sharedComponent;
base.OnComponentInit(uid, component, args);
if (HasComp<ApcPowerReceiverComponent>(component.Owner))
{

View File

@@ -1,7 +1,7 @@
using Content.Server.Power.Components;
using Content.Server.Projectiles.Components;
using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Content.Shared.Projectiles;
using Content.Shared.Verbs;
using Content.Shared.Weapons.Ranged;
using Content.Shared.Weapons.Ranged.Components;

View File

@@ -1,7 +1,7 @@
using Content.Server.Projectiles.Components;
using Content.Shared.Damage;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Projectiles;
using Content.Shared.Verbs;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Prototypes;

View File

@@ -1,10 +1,8 @@
using System.Linq;
using Content.Server.Cargo.Systems;
using Content.Server.Damage.Systems;
using Content.Server.Examine;
using Content.Server.Interaction;
using Content.Server.Interaction.Components;
using Content.Server.Projectiles.Components;
using Content.Server.Stunnable;
using Content.Server.Weapons.Melee;
using Content.Server.Weapons.Ranged.Components;
@@ -12,6 +10,7 @@ using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Projectiles;
using Content.Shared.Weapons.Melee;
using Content.Shared.Weapons.Ranged;
using Content.Shared.Weapons.Ranged.Components;

View File

@@ -25,12 +25,12 @@ namespace Content.Shared.Construction.Steps
public override bool EntityValid(EntityUid uid, IEntityManager entityManager)
{
return entityManager.TryGetComponent(uid, out SharedStackComponent? stack) && stack.StackTypeId == MaterialPrototypeId && stack.Count >= Amount;
return entityManager.TryGetComponent(uid, out StackComponent? stack) && stack.StackTypeId == MaterialPrototypeId && stack.Count >= Amount;
}
public bool EntityValid(EntityUid entity, [NotNullWhen(true)] out SharedStackComponent? stack)
public bool EntityValid(EntityUid entity, [NotNullWhen(true)] out StackComponent? stack)
{
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out SharedStackComponent? otherStack) && otherStack.StackTypeId == MaterialPrototypeId && otherStack.Count >= Amount)
if (IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out StackComponent? otherStack) && otherStack.StackTypeId == MaterialPrototypeId && otherStack.Count >= Amount)
stack = otherStack;
else
stack = null;

View File

@@ -3,11 +3,11 @@ using Robust.Shared.Serialization;
namespace Content.Shared.Flash
{
[NetworkedComponent, Access(typeof(SharedFlashSystem))]
public abstract class SharedFlashableComponent : Component
[RegisterComponent, NetworkedComponent]
public sealed class FlashableComponent : Component
{
public float Duration { get; set; }
public TimeSpan LastFlash { get; set; }
public float Duration;
public TimeSpan LastFlash;
public override bool SendOnlyToOwner => true;
}

View File

@@ -8,10 +8,10 @@ namespace Content.Shared.Flash
{
base.Initialize();
SubscribeLocalEvent<SharedFlashableComponent, ComponentGetState>(OnFlashableGetState);
SubscribeLocalEvent<FlashableComponent, ComponentGetState>(OnFlashableGetState);
}
private static void OnFlashableGetState(EntityUid uid, SharedFlashableComponent component, ref ComponentGetState args)
private static void OnFlashableGetState(EntityUid uid, FlashableComponent component, ref ComponentGetState args)
{
args.State = new FlashableComponentState(component.Duration, component.LastFlash);
}

View File

@@ -1,10 +1,14 @@
using Content.Shared.Humanoid.Markings;
using Content.Shared.Humanoid.Prototypes;
using Robust.Shared.Enums;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Humanoid;
public abstract class SharedHumanoidComponent : Component
[RegisterComponent, NetworkedComponent]
public sealed class HumanoidComponent : Component
{
/// <summary>
/// Current species. Dictates things like base body sprites,
@@ -32,6 +36,40 @@ public abstract class SharedHumanoidComponent : Component
[ViewVariables] public readonly HashSet<HumanoidVisualLayers> HiddenLayers = new();
[DataField("sex")] public Sex Sex = Sex.Male;
public MarkingSet CurrentMarkings = new();
/// <summary>
/// Any custom base layers this humanoid might have. See:
/// limb transplants (potentially), robotic arms, etc.
/// Stored on the server, this is merged in the client into
/// all layer settings.
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
public Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> CustomBaseLayers = new();
public HashSet<HumanoidVisualLayers> PermanentlyHidden = new();
public HashSet<HumanoidVisualLayers> AllHiddenLayers
{
get
{
var result = new HashSet<HumanoidVisualLayers>(HiddenLayers);
result.UnionWith(PermanentlyHidden);
return result;
}
}
// Couldn't these be somewhere else?
[ViewVariables] public Gender Gender = default!;
[ViewVariables] public int Age = 18;
[ViewVariables] public List<Marking> CurrentClientMarkings = new();
public Dictionary<HumanoidVisualLayers, HumanoidSpeciesSpriteLayer> BaseLayers = new();
public string LastSpecies = default!;
}
[DataDefinition]

View File

@@ -165,7 +165,7 @@ public abstract class SharedMaterialStorageSystem : EntitySystem
return false;
}
var multiplier = TryComp<SharedStackComponent>(toInsert, out var stackComponent) ? stackComponent.Count : 1;
var multiplier = TryComp<StackComponent>(toInsert, out var stackComponent) ? stackComponent.Count : 1;
var totalVolume = 0;
foreach (var (mat, vol) in component.Storage)
{

View File

@@ -1,11 +1,13 @@
using Content.Shared.Damage;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Projectiles
{
[NetworkedComponent, Access(typeof(SharedProjectileSystem))]
public abstract class SharedProjectileComponent : Component
[RegisterComponent, NetworkedComponent]
public sealed class ProjectileComponent : Component
{
[ViewVariables(VVAccess.ReadWrite), DataField("impactEffect", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
public string? ImpactEffect;
@@ -24,5 +26,23 @@ namespace Content.Shared.Projectiles
Dirty();
}
}
[DataField("damage", required: true)]
[ViewVariables(VVAccess.ReadWrite)]
public DamageSpecifier Damage = default!;
[DataField("deleteOnCollide")]
public bool DeleteOnCollide { get; } = true;
[DataField("ignoreResistances")]
public bool IgnoreResistances { get; } = false;
// Get that juicy FPS hit sound
[DataField("soundHit")] public SoundSpecifier? SoundHit;
[DataField("soundForce")]
public bool ForceSound = false;
public bool DamagedEntity;
}
}

View File

@@ -12,10 +12,10 @@ namespace Content.Shared.Projectiles
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SharedProjectileComponent, PreventCollideEvent>(PreventCollision);
SubscribeLocalEvent<ProjectileComponent, PreventCollideEvent>(PreventCollision);
}
private void PreventCollision(EntityUid uid, SharedProjectileComponent component, ref PreventCollideEvent args)
private void PreventCollision(EntityUid uid, ProjectileComponent component, ref PreventCollideEvent args)
{
if (component.IgnoreShooter && args.BodyB.Owner == component.Shooter)
{
@@ -23,7 +23,7 @@ namespace Content.Shared.Projectiles
}
}
public void SetShooter(SharedProjectileComponent component, EntityUid uid)
public void SetShooter(ProjectileComponent component, EntityUid uid)
{
if (component.Shooter == uid) return;

View File

@@ -1,32 +0,0 @@
using Robust.Shared.GameStates;
using Content.Shared.Singularity.EntitySystems;
namespace Content.Shared.Singularity.Components;
/// <summary>
/// A component that makes the associated entity accumulate energy when an associated event horizon consumes things.
/// Energy management is server-side.
/// </summary>
[NetworkedComponent]
public abstract class SharedSingularityComponent : Component
{
/// <summary>
/// The current level of the singularity.
/// Used as a scaling factor for things like visual size, event horizon radius, gravity well radius, radiation output, etc.
/// If you want to set this use <see cref="SharedSingularitySystem.SetLevel"/>().
/// </summary>
[DataField("level")]
[Access(friends:typeof(SharedSingularitySystem), Other=AccessPermissions.Read, Self=AccessPermissions.Read)]
public byte Level = 1;
/// <summary>
/// The amount of radiation this singularity emits per its level.
/// Has to be on shared in case someone attaches a RadiationPulseComponent to the singularity.
/// If you want to set this use <see cref="SharedSingularitySystem.SetRadsPerLevel"/>().
/// </summary>
[DataField("radsPerLevel")]
[Access(friends:typeof(SharedSingularitySystem), Other=AccessPermissions.Read, Self=AccessPermissions.Read)]
[ViewVariables(VVAccess.ReadWrite)]
public float RadsPerLevel = 2f;
}

View File

@@ -1,23 +1,40 @@
using Content.Shared.Singularity.Components;
using Content.Server.Singularity.EntitySystems;
using Robust.Shared.GameStates;
using Content.Shared.Singularity.EntitySystems;
using Robust.Shared.Audio;
namespace Content.Server.Singularity.Components;
namespace Content.Shared.Singularity.Components;
/// <summary>
/// The server-side version of <see cref="SharedSingularityComponent">.
/// Primarily managed by <see cref="SingularitySystem">.
/// A component that makes the associated entity accumulate energy when an associated event horizon consumes things.
/// Energy management is server-side.
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(SharedSingularityComponent))]
public sealed class SingularityComponent : SharedSingularityComponent
[RegisterComponent, NetworkedComponent]
public sealed class SingularityComponent : Component
{
/// <summary>
/// The current level of the singularity.
/// Used as a scaling factor for things like visual size, event horizon radius, gravity well radius, radiation output, etc.
/// If you want to set this use <see cref="SharedSingularitySystem.SetLevel"/>().
/// </summary>
[DataField("level")]
[Access(friends:typeof(SharedSingularitySystem), Other=AccessPermissions.Read, Self=AccessPermissions.Read)]
public byte Level = 1;
/// <summary>
/// The amount of radiation this singularity emits per its level.
/// Has to be on shared in case someone attaches a RadiationPulseComponent to the singularity.
/// If you want to set this use <see cref="SharedSingularitySystem.SetRadsPerLevel"/>().
/// </summary>
[DataField("radsPerLevel")]
[Access(friends:typeof(SharedSingularitySystem), Other=AccessPermissions.Read, Self=AccessPermissions.Read)]
[ViewVariables(VVAccess.ReadWrite)]
public float RadsPerLevel = 2f;
/// <summary>
/// The amount of energy this singularity contains.
/// If you want to set this go through <see cref="SingularitySystem.SetEnergy"/>
/// </summary>
[DataField("energy")]
[Access(friends:typeof(SingularitySystem))]
public float Energy = 180f;
/// <summary>
@@ -40,7 +57,7 @@ public sealed class SingularityComponent : SharedSingularityComponent
);
/// <summary>
/// The audio stream that plays the sound specified by <see cref="AmbientSound"> on loop.
/// The audio stream that plays the sound specified by <see cref="AmbientSound"/> on loop.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public IPlayingAudioStream? AmbientSoundStream = null;
@@ -71,22 +88,18 @@ public sealed class SingularityComponent : SharedSingularityComponent
/// </summary>
[DataField("updatePeriod")]
[ViewVariables(VVAccess.ReadOnly)]
[Access(typeof(SingularitySystem))]
public TimeSpan TargetUpdatePeriod { get; internal set; } = TimeSpan.FromSeconds(1.0);
public TimeSpan TargetUpdatePeriod = TimeSpan.FromSeconds(1.0);
/// <summary>
/// The next time this singularity should be updated by <see cref="SingularitySystem"/>
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
[Access(typeof(SingularitySystem))]
public TimeSpan NextUpdateTime { get; internal set; } = default!;
public TimeSpan NextUpdateTime = default!;
/// <summary>
/// The last time this singularity was be updated by <see cref="SingularitySystem"/>
/// The last time this singularity was updated.
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
[Access(typeof(SingularitySystem))]
public TimeSpan LastUpdateTime { get; internal set; } = default!;
public TimeSpan LastUpdateTime = default!;
#endregion Update Timing
}

View File

@@ -10,7 +10,7 @@ using Content.Shared.Singularity.Events;
namespace Content.Shared.Singularity.EntitySystems;
/// <summary>
/// The entity system primarily responsible for managing <see cref="SharedSingularityComponent"/>s.
/// The entity system primarily responsible for managing <see cref="SingularityComponent"/>s.
/// </summary>
public abstract class SharedSingularitySystem : EntitySystem
{
@@ -44,7 +44,7 @@ public abstract class SharedSingularitySystem : EntitySystem
{
base.Initialize();
SubscribeLocalEvent<SharedSingularityComponent, ComponentStartup>(OnSingularityStartup);
SubscribeLocalEvent<SingularityComponent, ComponentStartup>(OnSingularityStartup);
SubscribeLocalEvent<AppearanceComponent, SingularityLevelChangedEvent>(UpdateAppearance);
SubscribeLocalEvent<RadiationSourceComponent, SingularityLevelChangedEvent>(UpdateRadiation);
SubscribeLocalEvent<PhysicsComponent, SingularityLevelChangedEvent>(UpdateBody);
@@ -53,16 +53,16 @@ public abstract class SharedSingularitySystem : EntitySystem
SubscribeLocalEvent<SingularityDistortionComponent, EntGotInsertedIntoContainerMessage>(UpdateDistortion);
SubscribeLocalEvent<SingularityDistortionComponent, EntGotRemovedFromContainerMessage>(UpdateDistortion);
var vvHandle = Vvm.GetTypeHandler<SharedSingularityComponent>();
vvHandle.AddPath(nameof(SharedSingularityComponent.Level), (_, comp) => comp.Level, SetLevel);
vvHandle.AddPath(nameof(SharedSingularityComponent.RadsPerLevel), (_, comp) => comp.RadsPerLevel, SetRadsPerLevel);
var vvHandle = Vvm.GetTypeHandler<SingularityComponent>();
vvHandle.AddPath(nameof(SingularityComponent.Level), (_, comp) => comp.Level, SetLevel);
vvHandle.AddPath(nameof(SingularityComponent.RadsPerLevel), (_, comp) => comp.RadsPerLevel, SetRadsPerLevel);
}
public override void Shutdown()
{
var vvHandle = Vvm.GetTypeHandler<SharedSingularityComponent>();
vvHandle.RemovePath(nameof(SharedSingularityComponent.Level));
vvHandle.RemovePath(nameof(SharedSingularityComponent.RadsPerLevel));
var vvHandle = Vvm.GetTypeHandler<SingularityComponent>();
vvHandle.RemovePath(nameof(SingularityComponent.Level));
vvHandle.RemovePath(nameof(SingularityComponent.RadsPerLevel));
base.Shutdown();
}
@@ -70,13 +70,13 @@ public abstract class SharedSingularitySystem : EntitySystem
#region Getters/Setters
/// <summary>
/// Setter for <see cref="SharedSingularityComponent.Level"/>
/// Setter for <see cref="SingularityComponent.Level"/>
/// Also sends out an event alerting that the singularities level has changed.
/// </summary>
/// <param name="uid">The uid of the singularity to change the level of.</param>
/// <param name="value">The new level the singularity should have.</param>
/// <param name="singularity">The state of the singularity to change the level of.</param>
public void SetLevel(EntityUid uid, byte value, SharedSingularityComponent? singularity = null)
public void SetLevel(EntityUid uid, byte value, SingularityComponent? singularity = null)
{
if(!Resolve(uid, ref singularity))
return;
@@ -93,13 +93,13 @@ public abstract class SharedSingularitySystem : EntitySystem
}
/// <summary>
/// Setter for <see cref="SharedSingularityComponent.RadsPerLevel"/>
/// Setter for <see cref="SingularityComponent.RadsPerLevel"/>
/// Also updates the radiation output of the singularity according to the new values.
/// </summary>
/// <param name="uid">The uid of the singularity to change the radioactivity of.</param>
/// <param name="value">The new radioactivity the singularity should have.</param>
/// <param name="singularity">The state of the singularity to change the radioactivity of.</param>
public void SetRadsPerLevel(EntityUid uid, float value, SharedSingularityComponent? singularity = null)
public void SetRadsPerLevel(EntityUid uid, float value, SingularityComponent? singularity = null)
{
if(!Resolve(uid, ref singularity))
return;
@@ -117,9 +117,9 @@ public abstract class SharedSingularitySystem : EntitySystem
/// Usually follows a SharedSingularitySystem.SetLevel call, but is also used on component startup to sync everything.
/// </summary>
/// <param name="uid">The uid of the singularity which's level has changed.</param>
/// <param name="oldValue">The old level of the singularity. May be equal to <see cref="SharedSingularityComponent.Level"/> if the component is starting.</param>
/// <param name="oldValue">The old level of the singularity. May be equal to <see cref="SingularityComponent.Level"/> if the component is starting.</param>
/// <param name="singularity">The state of the singularity which's level has changed.</param>
public void UpdateSingularityLevel(EntityUid uid, byte oldValue, SharedSingularityComponent? singularity = null)
public void UpdateSingularityLevel(EntityUid uid, byte oldValue, SingularityComponent? singularity = null)
{
if(!Resolve(uid, ref singularity))
return;
@@ -135,7 +135,7 @@ public abstract class SharedSingularitySystem : EntitySystem
/// </summary>
/// <param name="uid">The uid of the singularity.</param>
/// <param name="singularity">The state of the singularity.</param>
public void UpdateSingularityLevel(EntityUid uid, SharedSingularityComponent? singularity = null)
public void UpdateSingularityLevel(EntityUid uid, SingularityComponent? singularity = null)
{
if (Resolve(uid, ref singularity))
UpdateSingularityLevel(uid, singularity.Level, singularity);
@@ -147,7 +147,7 @@ public abstract class SharedSingularitySystem : EntitySystem
/// <param name="uid">The uid of the singularity to update the radiation of.</param>
/// <param name="singularity">The state of the singularity to update the radiation of.</param>
/// <param name="rads">The state of the radioactivity of the singularity to update.</param>
private void UpdateRadiation(EntityUid uid, SharedSingularityComponent? singularity = null, RadiationSourceComponent? rads = null)
private void UpdateRadiation(EntityUid uid, SingularityComponent? singularity = null, RadiationSourceComponent? rads = null)
{
if(!Resolve(uid, ref singularity, ref rads, logMissing: false))
return;
@@ -177,7 +177,7 @@ public abstract class SharedSingularitySystem : EntitySystem
/// </summary>
/// <param name="singulo">A singularity.</param>
/// <returns>The gravity well radius the singularity should have given its state.</returns>
public float GravPulseRange(SharedSingularityComponent singulo)
public float GravPulseRange(SingularityComponent singulo)
=> BaseGravityWellRadius * (singulo.Level + 1);
/// <summary>
@@ -185,7 +185,7 @@ public abstract class SharedSingularitySystem : EntitySystem
/// </summary>
/// <param name="singulo">A singularity.</param>
/// <returns>The base gravitational acceleration the singularity should have given its state.</returns>
public (float, float) GravPulseAcceleration(SharedSingularityComponent singulo)
public (float, float) GravPulseAcceleration(SingularityComponent singulo)
=> (BaseGravityWellAcceleration * singulo.Level, 0f);
/// <summary>
@@ -193,7 +193,7 @@ public abstract class SharedSingularitySystem : EntitySystem
/// </summary>
/// <param name="singulo">A singularity.</param>
/// <returns>The event horizon radius the singularity should have given its state.</returns>
public float EventHorizonRadius(SharedSingularityComponent singulo)
public float EventHorizonRadius(SingularityComponent singulo)
=> (float) singulo.Level - 0.5f;
/// <summary>
@@ -201,7 +201,7 @@ public abstract class SharedSingularitySystem : EntitySystem
/// </summary>
/// <param name="singulo">A singularity.</param>
/// <returns>Whether the singularity should be able to breach containment.</returns>
public bool CanBreachContainment(SharedSingularityComponent singulo)
public bool CanBreachContainment(SingularityComponent singulo)
=> singulo.Level >= SingularityBreachThreshold;
/// <summary>
@@ -255,7 +255,7 @@ public abstract class SharedSingularitySystem : EntitySystem
/// </summary>
public readonly byte Level;
public SingularityComponentState(SharedSingularityComponent singulo)
public SingularityComponentState(SingularityComponent singulo)
{
Level = singulo.Level;
}
@@ -269,7 +269,7 @@ public abstract class SharedSingularitySystem : EntitySystem
/// <param name="uid">The entity that is becoming a singularity.</param>
/// <param name="comp">The singularity component that is being added to the entity.</param>
/// <param name="args">The event arguments.</param>
protected virtual void OnSingularityStartup(EntityUid uid, SharedSingularityComponent comp, ComponentStartup args)
protected virtual void OnSingularityStartup(EntityUid uid, SingularityComponent comp, ComponentStartup args)
{
UpdateSingularityLevel(uid, comp);
}

View File

@@ -20,9 +20,9 @@ public sealed class SingularityLevelChangedEvent : EntityEventArgs
/// <summary>
/// The singularity that just changed level.
/// </summary>
public readonly SharedSingularityComponent Singularity;
public readonly SingularityComponent Singularity;
public SingularityLevelChangedEvent(byte newValue, byte oldValue, SharedSingularityComponent singularity)
public SingularityLevelChangedEvent(byte newValue, byte oldValue, SingularityComponent singularity)
{
NewValue = newValue;
OldValue = oldValue;

View File

@@ -26,30 +26,30 @@ namespace Content.Shared.Stacks
{
base.Initialize();
SubscribeLocalEvent<SharedStackComponent, ComponentGetState>(OnStackGetState);
SubscribeLocalEvent<SharedStackComponent, ComponentHandleState>(OnStackHandleState);
SubscribeLocalEvent<SharedStackComponent, ComponentStartup>(OnStackStarted);
SubscribeLocalEvent<SharedStackComponent, ExaminedEvent>(OnStackExamined);
SubscribeLocalEvent<SharedStackComponent, InteractUsingEvent>(OnStackInteractUsing);
SubscribeLocalEvent<StackComponent, ComponentGetState>(OnStackGetState);
SubscribeLocalEvent<StackComponent, ComponentHandleState>(OnStackHandleState);
SubscribeLocalEvent<StackComponent, ComponentStartup>(OnStackStarted);
SubscribeLocalEvent<StackComponent, ExaminedEvent>(OnStackExamined);
SubscribeLocalEvent<StackComponent, InteractUsingEvent>(OnStackInteractUsing);
_vvm.GetTypeHandler<SharedStackComponent>()
.AddPath(nameof(SharedStackComponent.Count), (_, comp) => comp.Count, SetCount);
_vvm.GetTypeHandler<StackComponent>()
.AddPath(nameof(StackComponent.Count), (_, comp) => comp.Count, SetCount);
}
public override void Shutdown()
{
base.Shutdown();
_vvm.GetTypeHandler<SharedStackComponent>()
.RemovePath(nameof(SharedStackComponent.Count));
_vvm.GetTypeHandler<StackComponent>()
.RemovePath(nameof(StackComponent.Count));
}
private void OnStackInteractUsing(EntityUid uid, SharedStackComponent stack, InteractUsingEvent args)
private void OnStackInteractUsing(EntityUid uid, StackComponent stack, InteractUsingEvent args)
{
if (args.Handled)
return;
if (!TryComp(args.Used, out SharedStackComponent? recipientStack))
if (!TryComp(args.Used, out StackComponent? recipientStack))
return;
if (!TryMergeStacks(uid, args.Used, out var transfered, stack, recipientStack))
@@ -92,8 +92,8 @@ namespace Content.Shared.Stacks
EntityUid donor,
EntityUid recipient,
out int transfered,
SharedStackComponent? donorStack = null,
SharedStackComponent? recipientStack = null)
StackComponent? donorStack = null,
StackComponent? recipientStack = null)
{
transfered = 0;
if (!Resolve(recipient, ref recipientStack, false) || !Resolve(donor, ref donorStack, false))
@@ -118,7 +118,7 @@ namespace Content.Shared.Stacks
public void TryMergeToHands(
EntityUid item,
EntityUid user,
SharedStackComponent? itemStack = null,
StackComponent? itemStack = null,
SharedHandsComponent? hands = null)
{
if (!Resolve(user, ref hands, false))
@@ -143,7 +143,7 @@ namespace Content.Shared.Stacks
HandsSystem.PickupOrDrop(user, item, handsComp: hands);
}
public virtual void SetCount(EntityUid uid, int amount, SharedStackComponent? component = null)
public virtual void SetCount(EntityUid uid, int amount, StackComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
@@ -169,7 +169,7 @@ namespace Content.Shared.Stacks
/// <summary>
/// Try to use an amount of items on this stack. Returns whether this succeeded.
/// </summary>
public bool Use(EntityUid uid, int amount, SharedStackComponent? stack = null)
public bool Use(EntityUid uid, int amount, StackComponent? stack = null)
{
if (!Resolve(uid, ref stack))
return false;
@@ -199,7 +199,7 @@ namespace Content.Shared.Stacks
public int GetMaxCount(string entityId)
{
var entProto = _prototype.Index<EntityPrototype>(entityId);
entProto.TryGetComponent<SharedStackComponent>(out var stackComp);
entProto.TryGetComponent<StackComponent>(out var stackComp);
return GetMaxCount(stackComp);
}
@@ -211,7 +211,7 @@ namespace Content.Shared.Stacks
[PublicAPI]
public int GetMaxCount(EntityUid uid)
{
return GetMaxCount(CompOrNull<SharedStackComponent>(uid));
return GetMaxCount(CompOrNull<StackComponent>(uid));
}
/// <summary>
@@ -227,7 +227,7 @@ namespace Content.Shared.Stacks
/// </remarks>
/// <param name="component"></param>
/// <returns></returns>
public int GetMaxCount(SharedStackComponent? component)
public int GetMaxCount(StackComponent? component)
{
if (component == null)
return 1;
@@ -249,12 +249,12 @@ namespace Content.Shared.Stacks
/// <param name="component"></param>
/// <returns></returns>
[PublicAPI]
public int GetAvailableSpace(SharedStackComponent component)
public int GetAvailableSpace(StackComponent component)
{
return GetMaxCount(component) - component.Count;
}
private void OnStackStarted(EntityUid uid, SharedStackComponent component, ComponentStartup args)
private void OnStackStarted(EntityUid uid, StackComponent component, ComponentStartup args)
{
if (!TryComp(uid, out AppearanceComponent? appearance))
return;
@@ -264,12 +264,12 @@ namespace Content.Shared.Stacks
Appearance.SetData(uid, StackVisuals.Hide, false, appearance);
}
private void OnStackGetState(EntityUid uid, SharedStackComponent component, ref ComponentGetState args)
private void OnStackGetState(EntityUid uid, StackComponent component, ref ComponentGetState args)
{
args.State = new StackComponentState(component.Count, GetMaxCount(component));
}
private void OnStackHandleState(EntityUid uid, SharedStackComponent component, ref ComponentHandleState args)
private void OnStackHandleState(EntityUid uid, StackComponent component, ref ComponentHandleState args)
{
if (args.Current is not StackComponentState cast)
return;
@@ -279,7 +279,7 @@ namespace Content.Shared.Stacks
SetCount(uid, cast.Count, component);
}
private void OnStackExamined(EntityUid uid, SharedStackComponent component, ExaminedEvent args)
private void OnStackExamined(EntityUid uid, StackComponent component, ExaminedEvent args)
{
if (!args.IsInDetailsRange)
return;

View File

@@ -4,8 +4,8 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
namespace Content.Shared.Stacks
{
[NetworkedComponent, Access(typeof(SharedStackSystem))]
public abstract class SharedStackComponent : Component
[RegisterComponent, NetworkedComponent]
public sealed class StackComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("stackType", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<StackPrototype>))]
@@ -32,6 +32,12 @@ namespace Content.Shared.Stacks
[DataField("unlimited")]
[ViewVariables(VVAccess.ReadOnly)]
public bool Unlimited { get; set; }
[ViewVariables(VVAccess.ReadWrite)]
public bool ThrowIndividually { get; set; } = false;
[ViewVariables]
public bool UiUpdateNeeded { get; set; }
}
[Serializable, NetSerializable]

View File

@@ -32,7 +32,7 @@ namespace Content.Shared.Stacks
/// <summary>
/// The maximum amount of things that can be in a stack.
/// Can be overriden on <see cref="SharedStackComponent"/>
/// Can be overriden on <see cref="StackComponent"/>
/// if null, simply has unlimited max count.
/// </summary>
[DataField("maxCount")]

View File

@@ -5,23 +5,23 @@ using Robust.Shared.Utility;
namespace Content.Shared.Tools.Components
{
[NetworkedComponent]
public abstract class SharedMultipleToolComponent : Component
[RegisterComponent, NetworkedComponent]
public sealed class MultipleToolComponent : Component
{
[DataDefinition]
public sealed class ToolEntry
{
[DataField("behavior", required: true)]
public PrototypeFlags<ToolQualityPrototype> Behavior { get; } = new();
public PrototypeFlags<ToolQualityPrototype> Behavior = new();
[DataField("useSound")]
public SoundSpecifier? Sound { get; } = null;
public SoundSpecifier? Sound;
[DataField("changeSound")]
public SoundSpecifier? ChangeSound { get; } = null;
public SoundSpecifier? ChangeSound;
[DataField("sprite")]
public SpriteSpecifier? Sprite { get; } = null;
public SpriteSpecifier? Sprite;
}
[DataField("entries", required: true)]
@@ -31,7 +31,13 @@ namespace Content.Shared.Tools.Components
public uint CurrentEntry = 0;
[ViewVariables]
public string CurrentQualityName = String.Empty;
public string CurrentQualityName = string.Empty;
[ViewVariables(VVAccess.ReadWrite)]
public bool UiUpdateNeeded;
[DataField("statusShowBehavior")]
public bool StatusShowBehavior = true;
}
[NetSerializable, Serializable]

View File

@@ -13,13 +13,13 @@ public abstract class SharedToolSystem : EntitySystem
public override void Initialize()
{
SubscribeLocalEvent<SharedMultipleToolComponent, ComponentStartup>(OnMultipleToolStartup);
SubscribeLocalEvent<SharedMultipleToolComponent, ActivateInWorldEvent>(OnMultipleToolActivated);
SubscribeLocalEvent<SharedMultipleToolComponent, ComponentGetState>(OnMultipleToolGetState);
SubscribeLocalEvent<SharedMultipleToolComponent, ComponentHandleState>(OnMultipleToolHandleState);
SubscribeLocalEvent<MultipleToolComponent, ComponentStartup>(OnMultipleToolStartup);
SubscribeLocalEvent<MultipleToolComponent, ActivateInWorldEvent>(OnMultipleToolActivated);
SubscribeLocalEvent<MultipleToolComponent, ComponentGetState>(OnMultipleToolGetState);
SubscribeLocalEvent<MultipleToolComponent, ComponentHandleState>(OnMultipleToolHandleState);
}
private void OnMultipleToolHandleState(EntityUid uid, SharedMultipleToolComponent component, ref ComponentHandleState args)
private void OnMultipleToolHandleState(EntityUid uid, MultipleToolComponent component, ref ComponentHandleState args)
{
if (args.Current is not MultipleToolComponentState state)
return;
@@ -28,14 +28,14 @@ public abstract class SharedToolSystem : EntitySystem
SetMultipleTool(uid, component);
}
private void OnMultipleToolStartup(EntityUid uid, SharedMultipleToolComponent multiple, ComponentStartup args)
private void OnMultipleToolStartup(EntityUid uid, MultipleToolComponent multiple, ComponentStartup args)
{
// Only set the multiple tool if we have a tool component.
if(EntityManager.TryGetComponent(uid, out ToolComponent? tool))
SetMultipleTool(uid, multiple, tool);
}
private void OnMultipleToolActivated(EntityUid uid, SharedMultipleToolComponent multiple, ActivateInWorldEvent args)
private void OnMultipleToolActivated(EntityUid uid, MultipleToolComponent multiple, ActivateInWorldEvent args)
{
if (args.Handled)
return;
@@ -43,12 +43,12 @@ public abstract class SharedToolSystem : EntitySystem
args.Handled = CycleMultipleTool(uid, multiple, args.User);
}
private void OnMultipleToolGetState(EntityUid uid, SharedMultipleToolComponent multiple, ref ComponentGetState args)
private void OnMultipleToolGetState(EntityUid uid, MultipleToolComponent multiple, ref ComponentGetState args)
{
args.State = new MultipleToolComponentState(multiple.CurrentEntry);
}
public bool CycleMultipleTool(EntityUid uid, SharedMultipleToolComponent? multiple = null, EntityUid? user = null)
public bool CycleMultipleTool(EntityUid uid, MultipleToolComponent? multiple = null, EntityUid? user = null)
{
if (!Resolve(uid, ref multiple))
return false;
@@ -63,7 +63,7 @@ public abstract class SharedToolSystem : EntitySystem
}
public virtual void SetMultipleTool(EntityUid uid,
SharedMultipleToolComponent? multiple = null,
MultipleToolComponent? multiple = null,
ToolComponent? tool = null,
bool playSound = false,
EntityUid? user = null)

View File

@@ -1,100 +0,0 @@
using Content.Shared.Actions;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.VendingMachines
{
[NetworkedComponent()]
public abstract class SharedVendingMachineComponent : Component
{
/// <summary>
/// PrototypeID for the vending machine's inventory, see <see cref="VendingMachineInventoryPrototype"/>
/// </summary>
[DataField("pack", customTypeSerializer: typeof(PrototypeIdSerializer<VendingMachineInventoryPrototype>))]
public string PackPrototypeId = string.Empty;
/// <summary>
/// Used by the server to determine how long the vending machine stays in the "Deny" state.
/// Used by the client to determine how long the deny animation should be played.
/// </summary>
[DataField("denyDelay")]
public float DenyDelay = 2.0f;
/// <summary>
/// Used by the server to determine how long the vending machine stays in the "Eject" state.
/// The selected item is dispensed afer this delay.
/// Used by the client to determine how long the deny animation should be played.
/// </summary>
[DataField("ejectDelay")]
public float EjectDelay = 1.2f;
[ViewVariables]
public Dictionary<string, VendingMachineInventoryEntry> Inventory = new();
[ViewVariables]
public Dictionary<string, VendingMachineInventoryEntry> EmaggedInventory = new();
[ViewVariables]
public Dictionary<string, VendingMachineInventoryEntry> ContrabandInventory = new();
public bool Emagged;
public bool Contraband;
}
[Serializable, NetSerializable]
public sealed class VendingMachineInventoryEntry
{
[ViewVariables(VVAccess.ReadWrite)]
public InventoryType Type;
[ViewVariables(VVAccess.ReadWrite)]
public string ID;
[ViewVariables(VVAccess.ReadWrite)]
public uint Amount;
public VendingMachineInventoryEntry(InventoryType type, string id, uint amount)
{
Type = type;
ID = id;
Amount = amount;
}
}
[Serializable, NetSerializable]
public enum InventoryType : byte
{
Regular,
Emagged,
Contraband
}
[Serializable, NetSerializable]
public enum VendingMachineVisuals
{
VisualState
}
[Serializable, NetSerializable]
public enum VendingMachineVisualState
{
Normal,
Off,
Broken,
Eject,
Deny,
}
[Serializable, NetSerializable]
public enum ContrabandWireKey : byte
{
StatusKey,
TimeoutKey
}
[Serializable, NetSerializable]
public enum EjectWireKey : byte
{
StatusKey,
}
public sealed class VendingMachineSelfDispenseEvent : InstantActionEvent { };
}

View File

@@ -1,6 +1,5 @@
using Robust.Shared.Prototypes;
using System.Linq;
using static Content.Shared.VendingMachines.SharedVendingMachineComponent;
namespace Content.Shared.VendingMachines;
@@ -11,10 +10,10 @@ public abstract class SharedVendingMachineSystem : EntitySystem
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SharedVendingMachineComponent, ComponentInit>(OnComponentInit);;
SubscribeLocalEvent<VendingMachineComponent, ComponentInit>(OnComponentInit);
}
protected virtual void OnComponentInit(EntityUid uid, SharedVendingMachineComponent component, ComponentInit args)
protected virtual void OnComponentInit(EntityUid uid, VendingMachineComponent component, ComponentInit args)
{
if (!_prototypeManager.TryIndex(component.PackPrototypeId, out VendingMachineInventoryPrototype? packPrototype))
return;
@@ -26,13 +25,13 @@ public abstract class SharedVendingMachineSystem : EntitySystem
/// <summary>
/// Returns all of the vending machine's inventory. Only includes emagged and contraband inventories if
/// <see cref="SharedVendingMachineComponent.Emagged"/> and <see cref="SharedVendingMachineComponent.Contraband"/>
/// <see cref="VendingMachineComponent.Emagged"/> and <see cref="VendingMachineComponent.Contraband"/>
/// are <c>true</c> respectively.
/// </summary>
/// <param name="uid"></param>
/// <param name="component"></param>
/// <returns></returns>
public List<VendingMachineInventoryEntry> GetAllInventory(EntityUid uid, SharedVendingMachineComponent? component = null)
public List<VendingMachineInventoryEntry> GetAllInventory(EntityUid uid, VendingMachineComponent? component = null)
{
if (!Resolve(uid, ref component))
return new();
@@ -48,7 +47,7 @@ public abstract class SharedVendingMachineSystem : EntitySystem
return inventory;
}
public List<VendingMachineInventoryEntry> GetAvailableInventory(EntityUid uid, SharedVendingMachineComponent? component = null)
public List<VendingMachineInventoryEntry> GetAvailableInventory(EntityUid uid, VendingMachineComponent? component = null)
{
if (!Resolve(uid, ref component))
return new();
@@ -58,7 +57,7 @@ public abstract class SharedVendingMachineSystem : EntitySystem
private void AddInventoryFromPrototype(EntityUid uid, Dictionary<string, uint>? entries,
InventoryType type,
SharedVendingMachineComponent? component = null)
VendingMachineComponent? component = null)
{
if (!Resolve(uid, ref component) || entries == null)
{

View File

@@ -0,0 +1,241 @@
using Content.Shared.Actions;
using Content.Shared.Actions.ActionTypes;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.VendingMachines
{
[RegisterComponent, NetworkedComponent]
public sealed class VendingMachineComponent : Component
{
/// <summary>
/// PrototypeID for the vending machine's inventory, see <see cref="VendingMachineInventoryPrototype"/>
/// </summary>
[DataField("pack", customTypeSerializer: typeof(PrototypeIdSerializer<VendingMachineInventoryPrototype>))]
public string PackPrototypeId = string.Empty;
/// <summary>
/// Used by the server to determine how long the vending machine stays in the "Deny" state.
/// Used by the client to determine how long the deny animation should be played.
/// </summary>
[DataField("denyDelay")]
public float DenyDelay = 2.0f;
/// <summary>
/// Used by the server to determine how long the vending machine stays in the "Eject" state.
/// The selected item is dispensed afer this delay.
/// Used by the client to determine how long the deny animation should be played.
/// </summary>
[DataField("ejectDelay")]
public float EjectDelay = 1.2f;
[ViewVariables]
public Dictionary<string, VendingMachineInventoryEntry> Inventory = new();
[ViewVariables]
public Dictionary<string, VendingMachineInventoryEntry> EmaggedInventory = new();
[ViewVariables]
public Dictionary<string, VendingMachineInventoryEntry> ContrabandInventory = new();
public bool Emagged;
public bool Contraband;
public bool Ejecting;
public bool Denying;
public bool DispenseOnHitCoolingDown;
public string? NextItemToEject;
public bool Broken;
/// <summary>
/// When true, will forcefully throw any object it dispenses
/// </summary>
[DataField("speedLimiter")]
public bool CanShoot = false;
public bool ThrowNextItem = false;
/// <summary>
/// The chance that a vending machine will randomly dispense an item on hit.
/// Chance is 0 if null.
/// </summary>
[DataField("dispenseOnHitChance")]
public float? DispenseOnHitChance;
/// <summary>
/// The minimum amount of damage that must be done per hit to have a chance
/// of dispensing an item.
/// </summary>
[DataField("dispenseOnHitThreshold")]
public float? DispenseOnHitThreshold;
/// <summary>
/// Amount of time in seconds that need to pass before damage can cause a vending machine to eject again.
/// This value is separate to <see cref="VendingMachineComponent.EjectDelay"/> because that value might be
/// 0 for a vending machine for legitimate reasons (no desired delay/no eject animation)
/// and can be circumvented with forced ejections.
/// </summary>
[DataField("dispenseOnHitCooldown")]
public float? DispenseOnHitCooldown = 1.0f;
/// <summary>
/// Sound that plays when ejecting an item
/// </summary>
[DataField("soundVend")]
// Grabbed from: https://github.com/discordia-space/CEV-Eris/blob/f702afa271136d093ddeb415423240a2ceb212f0/sound/machines/vending_drop.ogg
public SoundSpecifier SoundVend = new SoundPathSpecifier("/Audio/Machines/machine_vend.ogg");
/// <summary>
/// Sound that plays when an item can't be ejected
/// </summary>
[DataField("soundDeny")]
// Yoinked from: https://github.com/discordia-space/CEV-Eris/blob/35bbad6764b14e15c03a816e3e89aa1751660ba9/sound/machines/Custom_deny.ogg
public SoundSpecifier SoundDeny = new SoundPathSpecifier("/Audio/Machines/custom_deny.ogg");
/// <summary>
/// The action available to the player controlling the vending machine
/// </summary>
[DataField("action", customTypeSerializer: typeof(PrototypeIdSerializer<InstantActionPrototype>))]
public string? Action = "VendingThrow";
public float NonLimitedEjectForce = 7.5f;
public float NonLimitedEjectRange = 5f;
public float EjectAccumulator = 0f;
public float DenyAccumulator = 0f;
public float DispenseOnHitAccumulator = 0f;
#region Client Visuals
/// <summary>
/// RSI state for when the vending machine is unpowered.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Base"/>
/// </summary>
[DataField("offState")]
public string? OffState;
/// <summary>
/// RSI state for the screen of the vending machine
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Screen"/>
/// </summary>
[DataField("screenState")]
public string? ScreenState;
/// <summary>
/// RSI state for the vending machine's normal state. Usually a looping animation.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
/// </summary>
[DataField("normalState")]
public string? NormalState;
/// <summary>
/// RSI state for the vending machine's eject animation.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
/// </summary>
[DataField("ejectState")]
public string? EjectState;
/// <summary>
/// RSI state for the vending machine's deny animation. Will either be played once as sprite flick
/// or looped depending on how <see cref="LoopDenyAnimation"/> is set.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.BaseUnshaded"/>
/// </summary>
[DataField("denyState")]
public string? DenyState;
/// <summary>
/// RSI state for when the vending machine is unpowered.
/// Will be displayed on the layer <see cref="VendingMachineVisualLayers.Base"/>
/// </summary>
[DataField("brokenState")]
public string? BrokenState;
/// <summary>
/// If set to <c>true</c> (default) will loop the animation of the <see cref="DenyState"/> for the duration
/// of <see cref="VendingMachineComponent.DenyDelay"/>. If set to <c>false</c> will play a sprite
/// flick animation for the state and then linger on the final frame until the end of the delay.
/// </summary>
[DataField("loopDeny")]
public bool LoopDenyAnimation = true;
#endregion
}
[Serializable, NetSerializable]
public sealed class VendingMachineInventoryEntry
{
[ViewVariables(VVAccess.ReadWrite)]
public InventoryType Type;
[ViewVariables(VVAccess.ReadWrite)]
public string ID;
[ViewVariables(VVAccess.ReadWrite)]
public uint Amount;
public VendingMachineInventoryEntry(InventoryType type, string id, uint amount)
{
Type = type;
ID = id;
Amount = amount;
}
}
[Serializable, NetSerializable]
public enum InventoryType : byte
{
Regular,
Emagged,
Contraband
}
[Serializable, NetSerializable]
public enum VendingMachineVisuals
{
VisualState
}
[Serializable, NetSerializable]
public enum VendingMachineVisualState
{
Normal,
Off,
Broken,
Eject,
Deny,
}
public enum VendingMachineVisualLayers : byte
{
/// <summary>
/// Off / Broken. The other layers will overlay this if the machine is on.
/// </summary>
Base,
/// <summary>
/// Normal / Deny / Eject
/// </summary>
BaseUnshaded,
/// <summary>
/// Screens that are persistent (where the machine is not off or broken)
/// </summary>
Screen
}
[Serializable, NetSerializable]
public enum ContrabandWireKey : byte
{
StatusKey,
TimeoutKey
}
[Serializable, NetSerializable]
public enum EjectWireKey : byte
{
StatusKey,
}
public sealed class VendingMachineSelfDispenseEvent : InstantActionEvent
{
};
}

View File

@@ -216,7 +216,6 @@
# trash: FoodPlateSmall
- type: Stack
stackType: Pancake
max: 9
count: 1
- type: Sprite
state: pancakes1
@@ -249,7 +248,6 @@
# trash: FoodPlateSmall
- type: Stack
stackType: Pancake
max: 3
count: 1
- type: Sprite
state: pancakesbb1
@@ -276,7 +274,6 @@
# trash: FoodPlateSmall
- type: Stack
stackType: Pancake
max: 3
count: 1
- type: Sprite
state: pancakescc1

View File

@@ -48,7 +48,6 @@
components:
- type: Stack
stackType: PaperRolling
max: 5
count: 5
- type: Sprite
sprite: Objects/Consumable/Smokeables/Cigarettes/paper.rsi
@@ -80,7 +79,6 @@
components:
- type: Stack
stackType: CigaretteFilter
max: 5
count: 5
- type: Sprite
sprite: Objects/Consumable/Smokeables/Cigarettes/paper.rsi

View File

@@ -793,7 +793,7 @@
brokenState: broken
normalState: normal-unshaded
ejectState: eject-unshaded
ejectdelay: 1.8
ejectDelay: 1.8
- type: Advertise
pack: GoodCleanFunAds
- type: Sprite

View File

@@ -4,7 +4,7 @@
id: Pancake
name: pancake
spawn: FoodBakedPancake
maxCount: 30
maxCount: 3
# Food Containers
@@ -22,14 +22,14 @@
name: rolling paper
icon: { sprite: /Textures/Objects/Consumable/Smokeables/Cigarettes/paper.rsi, state: cigpaper }
spawn: PaperRolling
maxCount: 30
maxCount: 5
- type: stack
id: CigaretteFilter
name: cigarette filter
icon: { sprite: /Textures/Objects/Consumable/Smokeables/Cigarettes/paper.rsi, state: cigfilter }
spawn: CigaretteFilter
maxCount: 30
maxCount: 5
- type: stack
id: GroundTobacco