Portable Generator Rework (#19302)

This commit is contained in:
Pieter-Jan Briers
2023-08-25 20:40:42 +02:00
committed by GitHub
parent 50828363fe
commit bf16698efa
73 changed files with 1933 additions and 473 deletions

View File

@@ -1,19 +1,24 @@
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
namespace Content.Shared.Power.Generator;
/// <summary>
/// This is used for generators that run off some kind of fuel.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedGeneratorSystem))]
/// <remarks>
/// <para>
/// Generators must be anchored to be able to run.
/// </para>
/// </remarks>
/// <seealso cref="SharedGeneratorSystem"/>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedGeneratorSystem))]
public sealed partial class FuelGeneratorComponent : Component
{
/// <summary>
/// The amount of fuel left in the generator.
/// Is the generator currently running?
/// </summary>
[DataField("remainingFuel"), ViewVariables(VVAccess.ReadWrite)]
public float RemainingFuel;
[DataField("on"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public bool On;
/// <summary>
/// The generator's target power.
@@ -27,6 +32,15 @@ public sealed partial class FuelGeneratorComponent : Component
[DataField("maxTargetPower"), ViewVariables(VVAccess.ReadWrite)]
public float MaxTargetPower = 30_000.0f;
/// <summary>
/// The minimum target power.
/// </summary>
/// <remarks>
/// Setting this to any value above 0 means that the generator can't idle without consuming some amount of fuel.
/// </remarks>
[DataField("minTargetPower"), ViewVariables(VVAccess.ReadWrite)]
public float MinTargetPower = 1_000;
/// <summary>
/// The "optimal" power at which the generator is considered to be at 100% efficiency.
/// </summary>
@@ -45,43 +59,3 @@ public sealed partial class FuelGeneratorComponent : Component
[DataField("fuelEfficiencyConstant")]
public float FuelEfficiencyConstant = 1.3f;
}
/// <summary>
/// Sent to the server to adjust the targeted power level.
/// </summary>
[Serializable, NetSerializable]
public sealed class SetTargetPowerMessage : BoundUserInterfaceMessage
{
public int TargetPower;
public SetTargetPowerMessage(int targetPower)
{
TargetPower = targetPower;
}
}
/// <summary>
/// Contains network state for FuelGeneratorComponent.
/// </summary>
[Serializable, NetSerializable]
public sealed class SolidFuelGeneratorComponentBuiState : BoundUserInterfaceState
{
public float RemainingFuel;
public float TargetPower;
public float MaximumPower;
public float OptimalPower;
public SolidFuelGeneratorComponentBuiState(FuelGeneratorComponent component)
{
RemainingFuel = component.RemainingFuel;
TargetPower = component.TargetPower;
MaximumPower = component.MaxTargetPower;
OptimalPower = component.OptimalPower;
}
}
[Serializable, NetSerializable]
public enum GeneratorComponentUiKey
{
Key
}

View File

@@ -0,0 +1,33 @@
using Content.Shared.Atmos;
namespace Content.Shared.Power.Generator;
/// <summary>
/// Makes a generator emit a gas into the atmosphere when running.
/// </summary>
/// <remarks>
/// The amount of gas produced is linear with the amount of fuel used.
/// </remarks>
/// <seealso cref="SharedGeneratorSystem"/>
/// <seealso cref="FuelGeneratorComponent"/>
[RegisterComponent]
public sealed partial class GeneratorExhaustGasComponent : Component
{
/// <summary>
/// The type of gas that will be emitted by the generator.
/// </summary>
[DataField("gasType"), ViewVariables(VVAccess.ReadWrite)]
public Gas GasType = Gas.CarbonDioxide;
/// <summary>
/// The amount of moles of gas that should be produced when one unit of fuel is burned.
/// </summary>
[DataField("moleRatio"), ViewVariables(VVAccess.ReadWrite)]
public float MoleRatio = 1;
/// <summary>
/// The temperature of created gas.
/// </summary>
[DataField("temperature"), ViewVariables(VVAccess.ReadWrite)]
public float Temperature = Atmospherics.T0C + 100;
}

View File

@@ -0,0 +1,61 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
namespace Content.Shared.Power.Generator;
/// <summary>
/// Enables a generator to switch between HV and MV output.
/// </summary>
/// <remarks>
/// Must have <c>CableDeviceNode</c>s for both <see cref="NodeOutputMV"/> and <see cref="NodeOutputHV"/>, and also a <c>PowerSupplierComponent</c>.
/// </remarks>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedPowerSwitchableGeneratorSystem))]
public sealed partial class PowerSwitchableGeneratorComponent : Component
{
/// <summary>
/// Which output the portable generator is currently connected to.
/// </summary>
[DataField("activeOutput")]
[AutoNetworkedField]
public PowerSwitchableGeneratorOutput ActiveOutput { get; set; }
/// <summary>
/// Sound that plays when the output is switched.
/// </summary>
/// <returns></returns>
[DataField("switchSound")]
public SoundSpecifier? SwitchSound { get; set; }
/// <summary>
/// Which node is the MV output?
/// </summary>
[DataField("nodeOutputMV")]
public string NodeOutputMV { get; set; } = "output_mv";
/// <summary>
/// Which node is the HV output?
/// </summary>
[DataField("nodeOutputHV")]
public string NodeOutputHV { get; set; } = "output_hv";
}
/// <summary>
/// Possible power output for power-switchable generators.
/// </summary>
/// <seealso cref="PowerSwitchableGeneratorComponent"/>
[Serializable, NetSerializable]
public enum PowerSwitchableGeneratorOutput : byte
{
/// <summary>
/// The generator is set to connect to a high-voltage power network.
/// </summary>
HV,
/// <summary>
/// The generator is set to connect to a medium-voltage power network.
/// </summary>
MV
}

View File

@@ -3,6 +3,7 @@
/// <summary>
/// This handles small, portable generators that run off a material fuel.
/// </summary>
/// <seealso cref="FuelGeneratorComponent"/>
public abstract class SharedGeneratorSystem : EntitySystem
{
/// <summary>

View File

@@ -0,0 +1,143 @@
using Robust.Shared.Audio;
using Robust.Shared.Serialization;
namespace Content.Shared.Power.Generator;
/// <summary>
/// Responsible for power output switching &amp; UI logic on portable generators.
/// </summary>
/// <remarks>
/// A portable generator is expected to have the following components: <c>SolidFuelGeneratorAdapterComponent</c> <see cref="FuelGeneratorComponent"/>.
/// </remarks>
/// <seealso cref="SharedPortableGeneratorSystem"/>
[RegisterComponent]
[Access(typeof(SharedPortableGeneratorSystem))]
public sealed partial class PortableGeneratorComponent : Component
{
/// <summary>
/// Chance that this generator will start. If it fails, the user has to try again.
/// </summary>
[DataField("startChance")]
[ViewVariables(VVAccess.ReadWrite)]
public float StartChance { get; set; } = 1f;
/// <summary>
/// Amount of time it takes to attempt to start the generator.
/// </summary>
[DataField("startTime")]
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan StartTime { get; set; } = TimeSpan.FromSeconds(2);
/// <summary>
/// Sound that plays when attempting to start this generator.
/// </summary>
[DataField("startSound")]
[ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier? StartSound { get; set; }
/// <summary>
/// Sound that plays when attempting to start this generator.
/// Plays instead of <see cref="StartSound"/> if the generator has no fuel (dumbass).
/// </summary>
[DataField("startSoundEmpty")]
[ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier? StartSoundEmpty { get; set; }
}
/// <summary>
/// Sent to the server to adjust the targeted power level of a portable generator.
/// </summary>
[Serializable, NetSerializable]
public sealed class PortableGeneratorSetTargetPowerMessage : BoundUserInterfaceMessage
{
public int TargetPower;
public PortableGeneratorSetTargetPowerMessage(int targetPower)
{
TargetPower = targetPower;
}
}
/// <summary>
/// Sent to the server to try to start a portable generator.
/// </summary>
[Serializable, NetSerializable]
public sealed class PortableGeneratorStartMessage : BoundUserInterfaceMessage
{
}
/// <summary>
/// Sent to the server to try to stop a portable generator.
/// </summary>
[Serializable, NetSerializable]
public sealed class PortableGeneratorStopMessage : BoundUserInterfaceMessage
{
}
/// <summary>
/// Sent to the server to try to change the power output of a power-switchable portable generator.
/// </summary>
[Serializable, NetSerializable]
public sealed class PortableGeneratorSwitchOutputMessage : BoundUserInterfaceMessage
{
}
/// <summary>
/// Sent to the server to try to eject all fuel stored in a portable generator.
/// </summary>
[Serializable, NetSerializable]
public sealed class PortableGeneratorEjectFuelMessage : BoundUserInterfaceMessage
{
}
/// <summary>
/// Contains network state for the portable generator.
/// </summary>
[Serializable, NetSerializable]
public sealed class PortableGeneratorComponentBuiState : BoundUserInterfaceState
{
public float RemainingFuel;
public bool Clogged;
public float TargetPower;
public float MaximumPower;
public float OptimalPower;
public bool On;
public PortableGeneratorComponentBuiState(FuelGeneratorComponent component, float remainingFuel, bool clogged)
{
RemainingFuel = remainingFuel;
Clogged = clogged;
TargetPower = component.TargetPower;
MaximumPower = component.MaxTargetPower;
OptimalPower = component.OptimalPower;
On = component.On;
}
}
[Serializable, NetSerializable]
public enum GeneratorComponentUiKey
{
Key
}
/// <summary>
/// Sprite layers for generator prototypes.
/// </summary>
[Serializable, NetSerializable]
public enum GeneratorVisualLayers : byte
{
Body,
Unlit
}
/// <summary>
/// Appearance keys for generators.
/// </summary>
[Serializable, NetSerializable]
public enum GeneratorVisuals : byte
{
/// <summary>
/// Boolean: is the generator running?
/// </summary>
Running,
}

View File

@@ -0,0 +1,25 @@
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;
namespace Content.Shared.Power.Generator;
/// <summary>
/// Shared logic for portable generators.
/// </summary>
/// <seealso cref="PortableGeneratorComponent"/>
public abstract class SharedPortableGeneratorSystem : EntitySystem
{
}
/// <summary>
/// Used to start a portable generator.
/// </summary>
/// <seealso cref="SharedPortableGeneratorSystem"/>
[Serializable, NetSerializable]
public sealed partial class GeneratorStartedEvent : DoAfterEvent
{
public override DoAfterEvent Clone()
{
return this;
}
}

View File

@@ -0,0 +1,23 @@
using Content.Shared.Examine;
namespace Content.Shared.Power.Generator;
/// <summary>
/// Shared logic for power-switchable generators.
/// </summary>
/// <seealso cref="PowerSwitchableGeneratorComponent"/>
public abstract class SharedPowerSwitchableGeneratorSystem : EntitySystem
{
public override void Initialize()
{
SubscribeLocalEvent<PowerSwitchableGeneratorComponent, ExaminedEvent>(GeneratorExamined);
}
private void GeneratorExamined(EntityUid uid, PowerSwitchableGeneratorComponent component, ExaminedEvent args)
{
// Show which output is currently selected.
args.PushMarkup(Loc.GetString(
"power-switchable-generator-examine",
("output", component.ActiveOutput.ToString())));
}
}