diff --git a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs index 7d06a4d41f..039290ccd5 100644 --- a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -33,7 +33,7 @@ namespace Content.Client.GameObjects.Components.Instruments [CanBeNull] private IMidiRenderer _renderer; - private int _instrumentProgram = 1; + private byte _instrumentProgram = 1; [ViewVariables] private readonly Queue> _midiQueue = new Queue<(MidiEvent, double)>(); @@ -66,7 +66,7 @@ namespace Content.Client.GameObjects.Components.Instruments /// Changes the instrument the midi renderer will play. /// [ViewVariables(VVAccess.ReadWrite)] - public int InstrumentProgram + public byte InstrumentProgram { get => _instrumentProgram; set @@ -91,10 +91,23 @@ namespace Content.Client.GameObjects.Components.Instruments [ViewVariables] public bool IsInputOpen => _renderer?.Status == MidiRendererStatus.Input; + /// + /// Whether the midi renderer is alive or not. + /// + [ViewVariables] + public bool IsRendererAlive => _renderer != null; + public override void Initialize() { base.Initialize(); IoCManager.InjectDependencies(this); + } + + protected void SetupRenderer() + { + if (IsRendererAlive) + return; + _renderer = _midiManager.GetNewRenderer(); if (_renderer != null) @@ -105,16 +118,22 @@ namespace Content.Client.GameObjects.Components.Instruments } } + protected void EndRenderer() + { + Timer.Spawn(1000, () => { _renderer?.Dispose(); }); + _renderer = null; + } + protected override void Shutdown() { base.Shutdown(); - _renderer?.Dispose(); + EndRenderer(); } public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); - serializer.DataField(ref _instrumentProgram, "program", 1); + serializer.DataField(ref _instrumentProgram, "program", (byte)1); } public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null) @@ -130,7 +149,7 @@ namespace Content.Client.GameObjects.Components.Instruments { case InstrumentMidiEventMessage midiEventMessage: // If we're the ones sending the MidiEvents, we ignore this message. - if (IsInputOpen || IsMidiOpen) break; + if (!IsRendererAlive || IsInputOpen || IsMidiOpen) break; for (var i = 0; i < midiEventMessage.MidiEvent.Length; i++) { //_midiQueue.Enqueue((midiEventMessage.MidiEvent[i], (i == 0 ? 0 : 0) + _gameTiming.CurTime.TotalSeconds - midiEventMessage.Timestamp[i])); @@ -146,12 +165,19 @@ namespace Content.Client.GameObjects.Components.Instruments if (IsInputOpen) CloseInput(); if (IsMidiOpen) CloseMidi(); break; + + case InstrumentStartMidiMessage _: + SetupRenderer(); + break; } } /// public bool OpenInput() { + SetupRenderer(); + SendNetworkMessage(new InstrumentStartMidiMessage()); + if (_renderer != null && _renderer.OpenInput()) { _renderer.OnMidiEvent += RendererOnMidiEvent; @@ -169,13 +195,16 @@ namespace Content.Client.GameObjects.Components.Instruments return false; } - _renderer.OnMidiEvent -= RendererOnMidiEvent; + EndRenderer(); return true; } /// public bool OpenMidi(string filename) { + SetupRenderer(); + SendNetworkMessage(new InstrumentStartMidiMessage()); + if (_renderer == null || !_renderer.OpenMidi(filename)) { return false; @@ -193,7 +222,7 @@ namespace Content.Client.GameObjects.Components.Instruments return false; } - _renderer.OnMidiEvent -= RendererOnMidiEvent; + EndRenderer(); return true; } @@ -206,7 +235,7 @@ namespace Content.Client.GameObjects.Components.Instruments _midiQueue.Enqueue((midiEvent, _gameTiming.CurTime.TotalSeconds)); } - public void Update(float delta) + public override void Update(float delta) { _timer -= delta; diff --git a/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs index b6512b8ee6..e7c01d61a8 100644 --- a/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -18,12 +18,17 @@ namespace Content.Server.GameObjects.Components.Instruments public class InstrumentComponent : SharedInstrumentComponent, IDropped, IHandSelected, IHandDeselected, IActivate, IUse, IThrown { + public const int MidiEventsPerSecond = 10; + /// /// The client channel currently playing the instrument, or null if there's none. /// private ICommonSession _instrumentPlayer; private bool _handheld; + private float _timer = 0f; + private int _midiEventCount = 1; + [ViewVariables] private BoundUserInterface _userInterface; @@ -57,6 +62,12 @@ namespace Content.Server.GameObjects.Components.Instruments case InstrumentMidiEventMessage midiEventMsg: SendNetworkMessage(midiEventMsg); break; + case InstrumentStartMidiMessage startMidi: + SendNetworkMessage(startMidi); + break; + case InstrumentStopMidiMessage stopMidi: + SendNetworkMessage(stopMidi); + break; } } @@ -124,5 +135,10 @@ namespace Content.Server.GameObjects.Components.Instruments { _userInterface.Open(session); } + + public override void Update(float delta) + { + base.Update(delta); + } } } diff --git a/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs b/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs index 9734425b3c..96d3ab9fc4 100644 --- a/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs +++ b/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs @@ -9,6 +9,10 @@ namespace Content.Shared.GameObjects.Components.Instruments { public override string Name => "Instrument"; public override uint? NetID => ContentNetIDs.INSTRUMENTS; + + public virtual void Update(float delta) + { + } } @@ -20,6 +24,14 @@ namespace Content.Shared.GameObjects.Components.Instruments { } + /// + /// This message is sent to the client to start the synth. + /// + [Serializable, NetSerializable] + public class InstrumentStartMidiMessage : ComponentMessage + { + } + /// /// This message carries a MidiEvent to be played on clients. /// diff --git a/Content.Shared/GameObjects/EntitySystems/SharedInstrumentSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedInstrumentSystem.cs index 6303475c30..577d1542bd 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedInstrumentSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedInstrumentSystem.cs @@ -1,15 +1,15 @@ -using Content.Client.GameObjects.Components.Instruments; +using Content.Shared.GameObjects.Components.Instruments; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; -namespace Content.Client.GameObjects.EntitySystems +namespace Content.Shared.GameObjects.EntitySystems { public class InstrumentSystem : EntitySystem { public override void Initialize() { base.Initialize(); - EntityQuery = new TypeEntityQuery(typeof(InstrumentComponent)); + EntityQuery = new TypeEntityQuery(typeof(SharedInstrumentComponent)); } public override void Update(float frameTime) @@ -18,7 +18,7 @@ namespace Content.Client.GameObjects.EntitySystems foreach (var entity in RelevantEntities) { - entity.GetComponent().Update(frameTime); + entity.GetComponent().Update(frameTime); } } }