private void OnMidiEventRx(InstrumentMidiEventEvent midiEv)
        {
            var uid = midiEv.Uid;

            if (!EntityManager.TryGetComponent(uid, out InstrumentComponent? instrument))
            {
                return;
            }

            var renderer = instrument.Renderer;

            if (renderer != null)
            {
                // If we're the ones sending the MidiEvents, we ignore this message.
                if (instrument.IsInputOpen || instrument.IsMidiOpen)
                {
                    return;
                }
            }
            else
            {
                // if we haven't started or finished some sequence
                if (instrument.SequenceStartTick == 0)
                {
                    // we may have arrived late
                    SetupRenderer(uid, true, instrument);
                }

                // might be our own notes after we already finished playing
                return;
            }

            if (instrument.SequenceStartTick <= 0)
            {
                instrument.SequenceStartTick = midiEv.MidiEvent.Min(x => x.Tick) - 1;
            }

            var sqrtLag = MathF.Sqrt(_netManager.ServerChannel !.Ping / 1000f);
            var delay   = (uint)(renderer.SequencerTimeScale * (.2 + sqrtLag));
            var delta   = delay - instrument.SequenceStartTick;

            instrument.SequenceDelay = Math.Max(instrument.SequenceDelay, delta);

            var currentTick = renderer.SequencerTick;

            // ReSharper disable once ForCanBeConvertedToForeach
            for (var i = 0; i < midiEv.MidiEvent.Length; i++)
            {
                var ev        = midiEv.MidiEvent[i];
                var scheduled = ev.Tick + instrument.SequenceDelay;

                if (scheduled <= currentTick)
                {
                    instrument.SequenceDelay += currentTick - ev.Tick;
                    scheduled = ev.Tick + instrument.SequenceDelay;
                }

                instrument.Renderer?.ScheduleMidiEvent(ev, scheduled, true);
            }
        }
    private void OnMidiEventRx(InstrumentMidiEventEvent msg, EntitySessionEventArgs args)
    {
        var uid = msg.Uid;

        if (!EntityManager.TryGetComponent(uid, out InstrumentComponent? instrument))
        {
            return;
        }

        if (!instrument.Playing ||
            args.SenderSession != instrument.InstrumentPlayer ||
            instrument.InstrumentPlayer == null ||
            args.SenderSession.AttachedEntity is not {
        } attached)
        {
            return;
        }

        var send = true;

        var minTick = msg.MidiEvent.Min(x => x.Tick);

        if (instrument.LastSequencerTick > minTick)
        {
            instrument.LaggedBatches++;

            if (instrument.RespectMidiLimits)
            {
                if (instrument.LaggedBatches == (int)(MaxMidiLaggedBatches * (1 / 3d) + 1))
                {
                    attached.PopupMessage(
                        Loc.GetString("instrument-component-finger-cramps-light-message"));
                }
                else if (instrument.LaggedBatches == (int)(MaxMidiLaggedBatches * (2 / 3d) + 1))
                {
                    attached.PopupMessage(
                        Loc.GetString("instrument-component-finger-cramps-serious-message"));
                }
            }

            if (instrument.LaggedBatches > MaxMidiLaggedBatches)
            {
                send = false;
            }
        }

        if (++instrument.MidiEventCount > MaxMidiEventsPerSecond ||
            msg.MidiEvent.Length > MaxMidiEventsPerBatch)
        {
            instrument.BatchesDropped++;

            send = false;
        }

        if (send || !instrument.RespectMidiLimits)
        {
            RaiseNetworkEvent(msg);
        }

        var maxTick = msg.MidiEvent.Max(x => x.Tick);

        instrument.LastSequencerTick = Math.Max(maxTick, minTick);
    }