protected override void Init()
        {
            base.Init();

            _car = GetComponent <TrainCar>();

            if (Authoritative)
            {
                _cargoState = new CargoStateUpdatePacket {
                    Id = Id
                };
            }
            else
            {
                GetComponent <DamageController>()?.SetupListeners(false);
                GetComponent <CarDamageModel>()?.SetupListeners(false);
                GetComponent <CargoDamageModel>()?.SetupListeners(false);
            }

            _coupleState = new CoupleStateUpdatePacket[_car.couplers.Length];
            for (var i = 0; i < _car.couplers.Length; i++)
            {
                _coupleState[i] = new CoupleStateUpdatePacket()
                {
                    Id = Id
                };
                PopulateCoupleStatePacket(_coupleState[i], i);
            }
        }
        private bool PopulateCoupleStatePacket(CoupleStateUpdatePacket state, int couplerNum)
        {
            var coupler        = _car.couplers[couplerNum];
            var otherCoupler   = coupler.coupledTo ?? coupler.GetAirHoseConnectedTo();
            var otherCoupleNum = Array.IndexOf(otherCoupler?.train.couplers ?? Array.Empty <Coupler>(), otherCoupler);

            var flags = (CoupleStateFlags)couplerNum & CoupleStateFlags.OwnCouplerIdMask;

            flags |= (CoupleStateFlags)(otherCoupleNum << 4) & CoupleStateFlags.OtherCouplerIdMask;
            flags |= coupler.hoseAndCock.IsHoseConnected ? CoupleStateFlags.HoseConnected : 0;
            flags |= coupler.IsCockOpen ? CoupleStateFlags.CockOpen : 0;
            flags |= coupler.coupledTo ? CoupleStateFlags.ChainConnected : 0;

            return(SetStateValue(ref state.OtherTrainCar, otherCoupler?.train.GetComponent <NetworkObject>().Id ?? default) |
                   SetStateValue(ref state.Flags, flags));
        }
        public bool Receive(CoupleStateUpdatePacket packet, ClientId client)
        {
            if (packet.Id != Id)
            {
                return(false);
            }

            Logging <TrainCarSync> .LogDebug($"CoupleStateUpdatePacket: {packet.Flags & ~(CoupleStateFlags.OwnCouplerIdMask | CoupleStateFlags.OtherCouplerIdMask)} / {(int) (packet.Flags & CoupleStateFlags.OwnCouplerIdMask)} / {(int) (packet.Flags & CoupleStateFlags.OtherCouplerIdMask) >> 4} / {packet.OtherTrainCar}");

            var otherCar        = packet.OtherTrainCar ? CarSpawner.Instance.allCars.Find(tc => tc.GetComponent <NetworkObject>()?.Id == packet.OtherTrainCar) : default;
            var otherCouplerNum = (int)(packet.Flags & CoupleStateFlags.OtherCouplerIdMask) >> 4;
            var otherCoupler    = otherCar?.couplers[otherCouplerNum];
            var couplerNum      = (int)(packet.Flags & CoupleStateFlags.OwnCouplerIdMask);
            var coupler         = _car.couplers[couplerNum];

            if (otherCoupler && (packet.Flags & CoupleStateFlags.ChainConnected) != 0)
            {
                coupler.CoupleTo(otherCoupler, viaChainInteraction: true);
            }
            else
            {
                coupler.Uncouple(viaChainInteraction: true);
            }

            if (otherCoupler && (packet.Flags & CoupleStateFlags.HoseConnected) != 0)
            {
                coupler.ConnectAirHose(otherCoupler, true);
            }
            else
            {
                coupler.DisconnectAirHose(true);
            }

            coupler.IsCockOpen = (packet.Flags & CoupleStateFlags.CockOpen) != 0;

            return(true);
        }