namespace Content.Client.Instruments;
-[RegisterComponent, ComponentReference(typeof(SharedInstrumentComponent))]
+[RegisterComponent]
public sealed partial class InstrumentComponent : SharedInstrumentComponent
{
public event Action? OnMidiPlaybackEnded;
using Robust.Client.Audio.Midi;
using Robust.Shared.Audio.Midi;
using Robust.Shared.Configuration;
+using Robust.Shared.GameStates;
using Robust.Shared.Network;
using Robust.Shared.Timing;
namespace Content.Client.Instruments;
-[UsedImplicitly]
public sealed class InstrumentSystem : SharedInstrumentSystem
{
[Dependency] private readonly IClientNetManager _netManager = default!;
SubscribeNetworkEvent<InstrumentStopMidiEvent>(OnMidiStop);
SubscribeLocalEvent<InstrumentComponent, ComponentShutdown>(OnShutdown);
+ SubscribeLocalEvent<InstrumentComponent, ComponentHandleState>(OnHandleState);
+ }
+
+ private void OnHandleState(EntityUid uid, SharedInstrumentComponent component, ref ComponentHandleState args)
+ {
+ if (args.Current is not InstrumentComponentState state)
+ return;
+
+ component.Playing = state.Playing;
+ component.InstrumentProgram = state.InstrumentProgram;
+ component.InstrumentBank = state.InstrumentBank;
+ component.AllowPercussion = state.AllowPercussion;
+ component.AllowProgramChange = state.AllowProgramChange;
+ component.RespectMidiLimits = state.RespectMidiLimits;
+ component.Master = EnsureEntity<InstrumentComponent>(state.Master, uid);
+ component.FilteredChannels = state.FilteredChannels;
+
+ if (component.Playing)
+ SetupRenderer(uid, true, component);
+ else
+ EndRenderer(uid, true, component);
}
public override void Shutdown()
RaiseNetworkEvent(new InstrumentSetFilteredChannelEvent(GetNetEntity(uid), channel, value));
}
+ public override bool ResolveInstrument(EntityUid uid, ref SharedInstrumentComponent? component)
+ {
+ if (component is not null)
+ return true;
+
+ TryComp<InstrumentComponent>(uid, out var localComp);
+ component = localComp;
+ return component != null;
+ }
+
public override void SetupRenderer(EntityUid uid, bool fromStateChange, SharedInstrumentComponent? component = null)
{
- if (!Resolve(uid, ref component))
+ if (!ResolveInstrument(uid, ref component))
return;
if (component is not InstrumentComponent instrument)
public override void EndRenderer(EntityUid uid, bool fromStateChange, SharedInstrumentComponent? component = null)
{
- if (!Resolve(uid, ref component, false))
+ if (!ResolveInstrument(uid, ref component))
return;
if (component is not InstrumentComponent instrument)
namespace Content.Server.Instruments;
-[RegisterComponent, ComponentReference(typeof(SharedInstrumentComponent))]
+[RegisterComponent]
public sealed partial class InstrumentComponent : SharedInstrumentComponent
{
[Dependency] private readonly IEntityManager _entMan = default!;
using Robust.Shared.Collections;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
+using Robust.Shared.GameStates;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
SubscribeLocalEvent<InstrumentComponent, BoundUIOpenedEvent>(OnBoundUIOpened);
SubscribeLocalEvent<InstrumentComponent, InstrumentBandRequestBuiMessage>(OnBoundUIRequestBands);
+ SubscribeLocalEvent<InstrumentComponent, ComponentGetState>(OnStrumentGetState);
+
_conHost.RegisterCommand("addtoband", AddToBandCommand);
}
+ private void OnStrumentGetState(EntityUid uid, InstrumentComponent component, ref ComponentGetState args)
+ {
+ args.State = new InstrumentComponentState()
+ {
+ Playing = component.Playing,
+ InstrumentProgram = component.InstrumentProgram,
+ InstrumentBank = component.InstrumentBank,
+ AllowPercussion = component.AllowPercussion,
+ AllowProgramChange = component.AllowProgramChange,
+ RespectMidiLimits = component.RespectMidiLimits,
+ Master = GetNetEntity(component.Master),
+ FilteredChannels = component.FilteredChannels
+ };
+ }
+
[AdminCommand(AdminFlags.Fun)]
private void AddToBandCommand(IConsoleShell shell, string _, string[] args)
{
if (_bui.TryGetUi(uid, InstrumentUiKey.Key, out var bui))
_bui.ToggleUi(bui, session);
}
+
+ public override bool ResolveInstrument(EntityUid uid, ref SharedInstrumentComponent? component)
+ {
+ if (component is not null)
+ return true;
+
+ TryComp<InstrumentComponent>(uid, out var localComp);
+ component = localComp;
+ return component != null;
+ }
}
if (!args.CanInteract || !args.CanAccess || component.InstrumentList.Count <= 1)
return;
- if (!TryComp<SharedInstrumentComponent>(uid, out var instrument))
+ if (!TryComp<InstrumentComponent>(uid, out var instrument))
return;
var priority = 0;
namespace Content.Shared.Instruments;
[NetworkedComponent]
-[AutoGenerateComponentState(true)]
[Access(typeof(SharedInstrumentSystem))]
public abstract partial class SharedInstrumentComponent : Component
{
- [ViewVariables, AutoNetworkedField]
+ [ViewVariables]
public bool Playing { get; set; }
- [DataField("program"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ [DataField("program"), ViewVariables(VVAccess.ReadWrite)]
public byte InstrumentProgram { get; set; }
- [DataField("bank"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ [DataField("bank"), ViewVariables(VVAccess.ReadWrite)]
public byte InstrumentBank { get; set; }
- [DataField("allowPercussion"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ [DataField("allowPercussion"), ViewVariables(VVAccess.ReadWrite)]
public bool AllowPercussion { get; set; }
- [DataField("allowProgramChange"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ [DataField("allowProgramChange"), ViewVariables(VVAccess.ReadWrite)]
public bool AllowProgramChange { get ; set; }
- [DataField("respectMidiLimits"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ [DataField("respectMidiLimits"), ViewVariables(VVAccess.ReadWrite)]
public bool RespectMidiLimits { get; set; } = true;
- [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ [ViewVariables(VVAccess.ReadWrite)]
public EntityUid? Master { get; set; } = null;
- [ViewVariables, AutoNetworkedField]
+ [ViewVariables]
public BitArray FilteredChannels { get; set; } = new(RobustMidiEvent.MaxChannels, true);
}
+[Serializable, NetSerializable]
+public sealed class InstrumentComponentState : ComponentState
+{
+ public bool Playing;
+
+ public byte InstrumentProgram;
+
+ public byte InstrumentBank;
+
+ public bool AllowPercussion;
+
+ public bool AllowProgramChange;
+
+ public bool RespectMidiLimits;
+
+ public NetEntity? Master;
+
+ public BitArray FilteredChannels = default!;
+}
+
/// <summary>
/// This message is sent to the client to completely stop midi input and midi playback.
public abstract class SharedInstrumentSystem : EntitySystem
{
- public override void Initialize()
- {
- SubscribeLocalEvent<SharedInstrumentComponent, AfterAutoHandleStateEvent>(AfterHandleInstrumentState);
- }
+ public abstract bool ResolveInstrument(EntityUid uid, ref SharedInstrumentComponent? component);
public virtual void SetupRenderer(EntityUid uid, bool fromStateChange, SharedInstrumentComponent? instrument = null)
{
component.InstrumentProgram = program;
Dirty(component);
}
-
- private void AfterHandleInstrumentState(EntityUid uid, SharedInstrumentComponent instrument, ref AfterAutoHandleStateEvent args)
- {
- if(instrument.Playing)
- SetupRenderer(uid, true, instrument);
- else
- EndRenderer(uid, true, instrument);
- }
}