* serv3 in shared pt 1 * beginning of deepclone api * progress in implementing ideepclone & serv3 in content * adds target * its cant hurt you it cant hurt you * more changes to content.server * adds dataclasses * almost there * renamed & edited entry * finishes refactoring content to use serv3 * gasmixture runtimes, next: reagentunit * fucin hell that was an annoying one * adds flags * fixes some yaml errors * removes comment * fixes generic components for now * removes todo actually clones values my god paul fixes bug involving resolving custom data classes from other proj renames dataclass fixes spritecomp adds WithFormat.Constants support * adds deepclone to ResistanceSet * adds a bunch of deepclone implementations adds a deepclone analyzer (TODO) adds a deep clone fallback for classes & structs * fixes a bunch of runtimes * adds deepclone to entityuid * adds generator to sln * gets rid of warnings * fixes * argh * componentdata refactors * more deepclone impl * heck me i reworked all of content deepclone * renames custom dataclasstarget * misc * reworks prototypes * deepclone nuke * renamed customdataclass attribute * fixes everything * misc fixed * the killcommit * getting there * changed yamlfieldattribute namespace * adds back iselfserialize * renames everything to data(field/definition) * ouch * Fix most errors on content * Fix more errors in content * Fix some components * work on tests * fixes some customdataclasses * fuggin shit * yes * yeas * Remove data classes * Data field naming fixes * arg * Git resetti RobustToolbox * Merge fixes * General fixes * Fix startup serialization errors * Fix DamageContainerPrototype when supported classes or types are null * Implement construction graph step type serializer * Fix up construction serialization * Fix up construction serialization part 2 * Fix null list in technology database component * Fix body serialization * Fix entity storage serialization * Fix actions serialization * Fix AI serialization * Fix reaction serialization * Fix body serialization * Fix grid atmosphere serialization * Rename IServ3Manager to ISerializationManager * Convert every non generic serializer to the new format, general fixes * Serialization and body system fix * pushinheritance fix * Update all prototypes to have a parent and have consistent id/parent properties * Merge fixes * smh my head * cuddling slaps * Content commit for engine PR * stuff * more fixes * argh * yes even you are fixed * changelog fixes * fixes seeds * argh * Test fixes * Add writing for alert order prototype * Fix alert order writing * FIX * its been alot ok * Fix the rest of the visualizers * Fix server alerts component tests * Fix alert prototype tests not using the read value * Fix alert prototype tests initializing serialization multiple times * THIS IS AN AMERICAN CODEBASE GOD BLESS THE USA * Add ImplicitDataDefinitionForInheritors to IMechanismBehavior Fixes the behaviors not being found * Fix NRE in strap component Good night to the 1 buckle optimization * Fix clothing component slot flags serialization tag * Fix body component in all components test * Merge fixes * ffs * Make construction graph prototype use serialization hooks * human yaml linted * a * Do the thing for construction * stuff * a * monke see yaml linter * LINT HARDER * Remove redundant todo * yes * Add skip hook argument to readers and copiers * we gamin * test/datafield fixes * adds more verbose validation * moves linter to action * Improve construction graph step type serializer error message * Fix ammo box component NRE * gamin * some updates to the linter * yes * removes that test * misc fixes * array fix priority fix misc fixes * adds proper info the validation * adds alwaysrelevant usa * Make yaml linter take half as long to run (~50% less) * Make yaml linter 5 times faster (~80% less execution time) * based vera being based * fixes mapsaving * warning cleanup & moves surpressor * removes old msbuild targets * Revert "Make yaml linter 5 times faster (~80% less execution time)" This reverts commit 3e6091359a26252c3e98828199553de668031c63. * Add -nowarn to yaml linter run configuration * Improve yaml linter message feedback * Make dependencies an argument instead of a property on the serialization manager * yamllinting slaps * Clean up type serializers * Move yaml linter code to its own method * Fix yaml errors * Change yaml linter action name and remove -nowarn * yaml linter please shut * Git resetti robust toolbox Co-authored-by: Paul <ritter.paul1+git@googlemail.com> Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
251 lines
8.0 KiB
C#
251 lines
8.0 KiB
C#
#nullable enable
|
|
using System;
|
|
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
|
|
using Content.Shared.GameObjects.Components.Power;
|
|
using Content.Shared.GameObjects.EntitySystems;
|
|
using Robust.Server.GameObjects;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Localization;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Serialization;
|
|
using Robust.Shared.Serialization.Manager.Attributes;
|
|
using Robust.Shared.Utility;
|
|
using Robust.Shared.ViewVariables;
|
|
|
|
namespace Content.Server.GameObjects.Components.Power.ApcNetComponents
|
|
{
|
|
/// <summary>
|
|
/// Attempts to link with a nearby <see cref="IPowerProvider"/>s so that it can receive power from a <see cref="IApcNet"/>.
|
|
/// </summary>
|
|
[RegisterComponent]
|
|
public class PowerReceiverComponent : Component, IExamine
|
|
{
|
|
[Dependency] private readonly IServerEntityManager _serverEntityManager = default!;
|
|
|
|
[ViewVariables] [ComponentDependency] private readonly IPhysicsComponent? _physicsComponent = null;
|
|
|
|
public override string Name => "PowerReceiver";
|
|
|
|
[ViewVariables]
|
|
public bool Powered => (HasApcPower || !NeedsPower) && !PowerDisabled;
|
|
|
|
/// <summary>
|
|
/// If this is being powered by an Apc.
|
|
/// </summary>
|
|
[ViewVariables]
|
|
public bool HasApcPower { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The max distance from a <see cref="PowerProviderComponent"/> that this can receive power from.
|
|
/// </summary>
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
|
public int PowerReceptionRange { get => _powerReceptionRange; set => SetPowerReceptionRange(value); }
|
|
[DataField("powerReceptionRange")]
|
|
private int _powerReceptionRange = 3;
|
|
|
|
[ViewVariables]
|
|
public IPowerProvider Provider { get => _provider; set => SetProvider(value); }
|
|
private IPowerProvider _provider = PowerProviderComponent.NullProvider;
|
|
|
|
/// <summary>
|
|
/// If this should be considered for connection by <see cref="PowerProviderComponent"/>s.
|
|
/// </summary>
|
|
public bool Connectable => Anchored;
|
|
|
|
private bool Anchored => _physicsComponent == null || _physicsComponent.Anchored;
|
|
|
|
[ViewVariables]
|
|
public bool NeedsProvider { get; private set; } = true;
|
|
|
|
/// <summary>
|
|
/// Amount of charge this needs from an APC per second to function.
|
|
/// </summary>
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
|
public int Load { get => _load; set => SetLoad(value); }
|
|
[DataField("powerLoad")]
|
|
private int _load = 5;
|
|
|
|
/// <summary>
|
|
/// When false, causes this to appear powered even if not receiving power from an Apc.
|
|
/// </summary>
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
|
public bool NeedsPower { get => _needsPower; set => SetNeedsPower(value); }
|
|
[DataField("needsPower")]
|
|
private bool _needsPower = true;
|
|
|
|
/// <summary>
|
|
/// When true, causes this to never appear powered.
|
|
/// </summary>
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
|
public bool PowerDisabled { get => _powerDisabled; set => SetPowerDisabled(value); }
|
|
[DataField("powerDisabled")]
|
|
private bool _powerDisabled;
|
|
|
|
protected override void Startup()
|
|
{
|
|
base.Startup();
|
|
if (NeedsProvider)
|
|
{
|
|
TryFindAndSetProvider();
|
|
}
|
|
if (_physicsComponent != null)
|
|
{
|
|
AnchorUpdate();
|
|
}
|
|
}
|
|
|
|
public override void OnRemove()
|
|
{
|
|
_provider.RemoveReceiver(this);
|
|
base.OnRemove();
|
|
}
|
|
|
|
public void TryFindAndSetProvider()
|
|
{
|
|
if (TryFindAvailableProvider(out var provider))
|
|
{
|
|
Provider = provider;
|
|
}
|
|
}
|
|
|
|
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
|
{
|
|
base.HandleMessage(message, component);
|
|
switch (message)
|
|
{
|
|
case AnchoredChangedMessage:
|
|
AnchorUpdate();
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ApcPowerChanged()
|
|
{
|
|
var oldPowered = Powered;
|
|
HasApcPower = Provider.HasApcPower;
|
|
if (Powered != oldPowered)
|
|
OnNewPowerState();
|
|
}
|
|
|
|
private bool TryFindAvailableProvider(out IPowerProvider foundProvider)
|
|
{
|
|
var nearbyEntities = _serverEntityManager
|
|
.GetEntitiesInRange(Owner, PowerReceptionRange);
|
|
|
|
foreach (var entity in nearbyEntities)
|
|
{
|
|
if (entity.TryGetComponent<PowerProviderComponent>(out var provider))
|
|
{
|
|
if (provider.Connectable)
|
|
{
|
|
if (provider.Owner.Transform.Coordinates.TryDistance(_serverEntityManager, Owner.Transform.Coordinates, out var distance))
|
|
{
|
|
if (distance < Math.Min(PowerReceptionRange, provider.PowerTransferRange))
|
|
{
|
|
foundProvider = provider;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
foundProvider = default!;
|
|
return false;
|
|
}
|
|
|
|
public void ClearProvider()
|
|
{
|
|
_provider.RemoveReceiver(this);
|
|
_provider = PowerProviderComponent.NullProvider;
|
|
NeedsProvider = true;
|
|
ApcPowerChanged();
|
|
}
|
|
|
|
private void SetProvider(IPowerProvider newProvider)
|
|
{
|
|
_provider.RemoveReceiver(this);
|
|
_provider = newProvider;
|
|
newProvider.AddReceiver(this);
|
|
NeedsProvider = false;
|
|
ApcPowerChanged();
|
|
}
|
|
|
|
private void SetPowerReceptionRange(int newPowerReceptionRange)
|
|
{
|
|
ClearProvider();
|
|
_powerReceptionRange = newPowerReceptionRange;
|
|
TryFindAndSetProvider();
|
|
}
|
|
|
|
private void SetLoad(int newLoad)
|
|
{
|
|
Provider.UpdateReceiverLoad(Load, newLoad);
|
|
_load = newLoad;
|
|
}
|
|
|
|
private void SetNeedsPower(bool newNeedsPower)
|
|
{
|
|
var oldPowered = Powered;
|
|
_needsPower = newNeedsPower;
|
|
if (oldPowered != Powered)
|
|
{
|
|
OnNewPowerState();
|
|
}
|
|
}
|
|
|
|
private void SetPowerDisabled(bool newPowerDisabled)
|
|
{
|
|
var oldPowered = Powered;
|
|
_powerDisabled = newPowerDisabled;
|
|
if (oldPowered != Powered)
|
|
{
|
|
OnNewPowerState();
|
|
}
|
|
}
|
|
|
|
private void OnNewPowerState()
|
|
{
|
|
SendMessage(new PowerChangedMessage(Powered));
|
|
|
|
if (Owner.TryGetComponent<AppearanceComponent>(out var appearance))
|
|
{
|
|
appearance.SetData(PowerDeviceVisuals.Powered, Powered);
|
|
}
|
|
}
|
|
|
|
private void AnchorUpdate()
|
|
{
|
|
if (Anchored)
|
|
{
|
|
if (NeedsProvider)
|
|
{
|
|
TryFindAndSetProvider();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ClearProvider();
|
|
}
|
|
}
|
|
|
|
///<summary>
|
|
///Adds some markup to the examine text of whatever object is using this component to tell you if it's powered or not, even if it doesn't have an icon state to do this for you.
|
|
///</summary>
|
|
public void Examine(FormattedMessage message, bool inDetailsRange)
|
|
{
|
|
message.AddMarkup(Loc.GetString("It appears to be {0}.", Powered ? "[color=darkgreen]powered[/color]" : "[color=darkred]un-powered[/color]"));
|
|
}
|
|
}
|
|
|
|
public class PowerChangedMessage : ComponentMessage
|
|
{
|
|
public readonly bool Powered;
|
|
|
|
public PowerChangedMessage(bool powered)
|
|
{
|
|
Powered = powered;
|
|
}
|
|
}
|
|
}
|