예제 #1
0
		protected void StreamReceived(NetworkingPlayer sender, BMSByte bytes)
		{
			if (TrackBandwidth)
				BandwidthIn += (ulong)bytes.Size;

			lock (tmp)
			{
				bytes.MoveStartIndex(1);
				readStream.Reset();

				if (base.ProcessReceivedData(sender, bytes, bytes[0]))
					return;

				// TODO:  Not needed after initialization
				readStream.SetProtocolType(Networking.ProtocolType.TCP);
				if (readStream.Consume(this, sender, bytes) == null)
					return;

				// Do not process player because it is processed through the listener
				if (readStream.identifierType == NetworkingStream.IdentifierType.Player)
				{
					if (!Connected)
						OnConnected();

					return;
				}

				if (readStream.Ready)
				{
					// TODO:  These need to be done better since there are many of them
					if (readStream.Bytes.Size < 22)
					{
						try
						{
							if (ObjectMapper.Compare<string>(readStream, "update"))
								UpdateNewPlayer(sender);

							if (ObjectMapper.Compare<string>(readStream, "disconnect"))
							{
								// TODO:  If this eventually sends something to the player they will not exist
								Disconnect(sender);
								return;
							}
						}
						catch
						{
							throw new NetworkException(12, "Mal-formed defalut communication");
						}
					}
				}

				if (ReadStream(sender, readStream) && IsServer)
					RelayStream(readStream);

				DataRead(sender, readStream);
			}
		}
예제 #2
0
		protected void OnRawDataRead(NetworkingPlayer sender, BMSByte data)
		{
			if (rawDataReadInvoker != null)
			{
				data.MoveStartIndex(sizeof(byte));
				rawDataReadInvoker(sender, data);
			}
		}
        protected override void ReadDirtyFields(BMSByte data, ulong timestep)
        {
            if (readDirtyFlags == null)
            {
                Initialize();
            }

            Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length);
            data.MoveStartIndex(readDirtyFlags.Length);

            if ((0x1 & readDirtyFlags[0]) != 0)
            {
                if (headPositionInterpolation.Enabled)
                {
                    headPositionInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    headPositionInterpolation.Timestep = timestep;
                }
                else
                {
                    _headPosition = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_headPosition(timestep);
                }
            }
            if ((0x2 & readDirtyFlags[0]) != 0)
            {
                if (headRotationInterpolation.Enabled)
                {
                    headRotationInterpolation.target   = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    headRotationInterpolation.Timestep = timestep;
                }
                else
                {
                    _headRotation = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    RunChange_headRotation(timestep);
                }
            }
            if ((0x4 & readDirtyFlags[0]) != 0)
            {
                if (leftPositionInterpolation.Enabled)
                {
                    leftPositionInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    leftPositionInterpolation.Timestep = timestep;
                }
                else
                {
                    _leftPosition = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_leftPosition(timestep);
                }
            }
            if ((0x8 & readDirtyFlags[0]) != 0)
            {
                if (leftRotationInterpolation.Enabled)
                {
                    leftRotationInterpolation.target   = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    leftRotationInterpolation.Timestep = timestep;
                }
                else
                {
                    _leftRotation = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    RunChange_leftRotation(timestep);
                }
            }
            if ((0x10 & readDirtyFlags[0]) != 0)
            {
                if (rightPositionInterpolation.Enabled)
                {
                    rightPositionInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    rightPositionInterpolation.Timestep = timestep;
                }
                else
                {
                    _rightPosition = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_rightPosition(timestep);
                }
            }
            if ((0x20 & readDirtyFlags[0]) != 0)
            {
                if (rightRotationInterpolation.Enabled)
                {
                    rightRotationInterpolation.target   = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    rightRotationInterpolation.Timestep = timestep;
                }
                else
                {
                    _rightRotation = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    RunChange_rightRotation(timestep);
                }
            }
        }
        protected override void ReadDirtyFields(BMSByte data, ulong timestep)
        {
            if (readDirtyFlags == null)
            {
                Initialize();
            }

            Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length);
            data.MoveStartIndex(readDirtyFlags.Length);

            if ((0x1 & readDirtyFlags[0]) != 0)
            {
                if (positionInterpolation.Enabled)
                {
                    positionInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    positionInterpolation.Timestep = timestep;
                }
                else
                {
                    _position = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_position(timestep);
                }
            }
            if ((0x2 & readDirtyFlags[0]) != 0)
            {
                if (rotationInterpolation.Enabled)
                {
                    rotationInterpolation.target   = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    rotationInterpolation.Timestep = timestep;
                }
                else
                {
                    _rotation = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    RunChange_rotation(timestep);
                }
            }
            if ((0x4 & readDirtyFlags[0]) != 0)
            {
                if (localVelocityInterpolation.Enabled)
                {
                    localVelocityInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    localVelocityInterpolation.Timestep = timestep;
                }
                else
                {
                    _localVelocity = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_localVelocity(timestep);
                }
            }
            if ((0x8 & readDirtyFlags[0]) != 0)
            {
                if (climbingInterpolation.Enabled)
                {
                    climbingInterpolation.target   = UnityObjectMapper.Instance.Map <bool>(data);
                    climbingInterpolation.Timestep = timestep;
                }
                else
                {
                    _climbing = UnityObjectMapper.Instance.Map <bool>(data);
                    RunChange_climbing(timestep);
                }
            }
            if ((0x10 & readDirtyFlags[0]) != 0)
            {
                if (runningInterpolation.Enabled)
                {
                    runningInterpolation.target   = UnityObjectMapper.Instance.Map <bool>(data);
                    runningInterpolation.Timestep = timestep;
                }
                else
                {
                    _running = UnityObjectMapper.Instance.Map <bool>(data);
                    RunChange_running(timestep);
                }
            }
            if ((0x20 & readDirtyFlags[0]) != 0)
            {
                if (aliveInterpolation.Enabled)
                {
                    aliveInterpolation.target   = UnityObjectMapper.Instance.Map <bool>(data);
                    aliveInterpolation.Timestep = timestep;
                }
                else
                {
                    _alive = UnityObjectMapper.Instance.Map <bool>(data);
                    RunChange_alive(timestep);
                }
            }
            if ((0x40 & readDirtyFlags[0]) != 0)
            {
                if (teamIndexInterpolation.Enabled)
                {
                    teamIndexInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    teamIndexInterpolation.Timestep = timestep;
                }
                else
                {
                    _teamIndex = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_teamIndex(timestep);
                }
            }
            if ((0x80 & readDirtyFlags[0]) != 0)
            {
                if (spawnPosInterpolation.Enabled)
                {
                    spawnPosInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    spawnPosInterpolation.Timestep = timestep;
                }
                else
                {
                    _spawnPos = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_spawnPos(timestep);
                }
            }
            if ((0x1 & readDirtyFlags[1]) != 0)
            {
                if (hasFlagInterpolation.Enabled)
                {
                    hasFlagInterpolation.target   = UnityObjectMapper.Instance.Map <bool>(data);
                    hasFlagInterpolation.Timestep = timestep;
                }
                else
                {
                    _hasFlag = UnityObjectMapper.Instance.Map <bool>(data);
                    RunChange_hasFlag(timestep);
                }
            }
            if ((0x2 & readDirtyFlags[1]) != 0)
            {
                if (attackingInterpolation.Enabled)
                {
                    attackingInterpolation.target   = UnityObjectMapper.Instance.Map <bool>(data);
                    attackingInterpolation.Timestep = timestep;
                }
                else
                {
                    _attacking = UnityObjectMapper.Instance.Map <bool>(data);
                    RunChange_attacking(timestep);
                }
            }
            if ((0x4 & readDirtyFlags[1]) != 0)
            {
                if (viewDirInterpolation.Enabled)
                {
                    viewDirInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    viewDirInterpolation.Timestep = timestep;
                }
                else
                {
                    _viewDir = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_viewDir(timestep);
                }
            }
        }
        protected override void ReadDirtyFields(BMSByte data, ulong timestep)
        {
            if (readDirtyFlags == null)
            {
                Initialize();
            }

            Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length);
            data.MoveStartIndex(readDirtyFlags.Length);

            if ((0x1 & readDirtyFlags[0]) != 0)
            {
                if (positionInterpolation.Enabled)
                {
                    positionInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    positionInterpolation.Timestep = timestep;
                }
                else
                {
                    _position = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_position(timestep);
                }
            }
            if ((0x2 & readDirtyFlags[0]) != 0)
            {
                if (rotationInterpolation.Enabled)
                {
                    rotationInterpolation.target   = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    rotationInterpolation.Timestep = timestep;
                }
                else
                {
                    _rotation = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    RunChange_rotation(timestep);
                }
            }
            if ((0x4 & readDirtyFlags[0]) != 0)
            {
                if (characterColorInterpolation.Enabled)
                {
                    characterColorInterpolation.target   = UnityObjectMapper.Instance.Map <Color>(data);
                    characterColorInterpolation.Timestep = timestep;
                }
                else
                {
                    _characterColor = UnityObjectMapper.Instance.Map <Color>(data);
                    RunChange_characterColor(timestep);
                }
            }
            if ((0x8 & readDirtyFlags[0]) != 0)
            {
                if (StrokeCountInterpolation.Enabled)
                {
                    StrokeCountInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    StrokeCountInterpolation.Timestep = timestep;
                }
                else
                {
                    _StrokeCount = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_StrokeCount(timestep);
                }
            }
            if ((0x10 & readDirtyFlags[0]) != 0)
            {
                if (HoleScoreInterpolation.Enabled)
                {
                    HoleScoreInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    HoleScoreInterpolation.Timestep = timestep;
                }
                else
                {
                    _HoleScore = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_HoleScore(timestep);
                }
            }
            if ((0x20 & readDirtyFlags[0]) != 0)
            {
                if (FinishedInterpolation.Enabled)
                {
                    FinishedInterpolation.target   = UnityObjectMapper.Instance.Map <bool>(data);
                    FinishedInterpolation.Timestep = timestep;
                }
                else
                {
                    _Finished = UnityObjectMapper.Instance.Map <bool>(data);
                    RunChange_Finished(timestep);
                }
            }
        }
예제 #6
0
        protected override void ReadDirtyFields(BMSByte data, ulong timestep)
        {
            if (readDirtyFlags == null)
            {
                Initialize();
            }

            Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length);
            data.MoveStartIndex(readDirtyFlags.Length);

            if ((0x1 & readDirtyFlags[0]) != 0)
            {
                if (aliveInterpolation.Enabled)
                {
                    aliveInterpolation.target   = UnityObjectMapper.Instance.Map <bool>(data);
                    aliveInterpolation.Timestep = timestep;
                }
                else
                {
                    _alive = UnityObjectMapper.Instance.Map <bool>(data);
                    RunChange_alive(timestep);
                }
            }

            if ((0x2 & readDirtyFlags[0]) != 0)
            {
                if (positionInterpolation.Enabled)
                {
                    positionInterpolation.target   = UnityObjectMapper.Instance.Map <Vector2>(data);
                    positionInterpolation.Timestep = timestep;
                }
                else
                {
                    _position = UnityObjectMapper.Instance.Map <Vector2>(data);
                    RunChange_position(timestep);
                }
            }

            if ((0x4 & readDirtyFlags[0]) != 0)
            {
                if (aimingPositionInterpolation.Enabled)
                {
                    aimingPositionInterpolation.target   = UnityObjectMapper.Instance.Map <Vector2>(data);
                    aimingPositionInterpolation.Timestep = timestep;
                }
                else
                {
                    _aimingPosition = UnityObjectMapper.Instance.Map <Vector2>(data);
                    RunChange_aimingPosition(timestep);
                }
            }

            if ((0x8 & readDirtyFlags[0]) != 0)
            {
                if (healthInterpolation.Enabled)
                {
                    healthInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    healthInterpolation.Timestep = timestep;
                }
                else
                {
                    _health = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_health(timestep);
                }
            }

            if ((0x10 & readDirtyFlags[0]) != 0)
            {
                if (weaponIndexInterpolation.Enabled)
                {
                    weaponIndexInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    weaponIndexInterpolation.Timestep = timestep;
                }
                else
                {
                    _weaponIndex = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_weaponIndex(timestep);
                }
            }
        }
        public override void Initialize(NetworkObject obj)
        {
            // We have already initialized this object
            if (networkObject != null && networkObject.AttachedBehavior != null)
            {
                return;
            }

            networkObject = (PlayerCharacterNetworkObject)obj;
            networkObject.AttachedBehavior = this;

            base.SetupHelperRpcs(networkObject);
            networkObject.RegisterRpc("SendInputs", SendInputs, typeof(ulong), typeof(Vector3), typeof(Quaternion));
            networkObject.RegisterRpc("StartGame", StartGame);
            networkObject.RegisterRpc("FireWeapon", FireWeapon, typeof(ulong), typeof(byte), typeof(Vector3), typeof(Vector3));
            networkObject.RegisterRpc("WeaponFired", WeaponFired, typeof(ulong), typeof(byte));
            networkObject.RegisterRpc("SetLocalPlayerId", SetLocalPlayerId, typeof(uint));
            networkObject.RegisterRpc("Die", Die, typeof(uint));
            networkObject.RegisterRpc("WeaponImpacted", WeaponImpacted, typeof(ulong), typeof(byte), typeof(long), typeof(Vector3));
            networkObject.RegisterRpc("Kill", Kill, typeof(uint));
            networkObject.RegisterRpc("UpdatePosition", UpdatePosition, typeof(ulong), typeof(Vector3), typeof(Quaternion), typeof(Vector3));
            networkObject.RegisterRpc("SendInputBuffer", SendInputBuffer, typeof(uint), typeof(byte[]));

            networkObject.onDestroy += DestroyGameObject;

            if (!obj.IsOwner)
            {
                if (!skipAttachIds.ContainsKey(obj.NetworkId))
                {
                    ProcessOthers(gameObject.transform, obj.NetworkId + 1);
                }
                else
                {
                    skipAttachIds.Remove(obj.NetworkId);
                }
            }

            if (obj.Metadata != null)
            {
                byte transformFlags = obj.Metadata[0];

                if (transformFlags != 0)
                {
                    BMSByte metadataTransform = new BMSByte();
                    metadataTransform.Clone(obj.Metadata);
                    metadataTransform.MoveStartIndex(1);

                    if ((transformFlags & 0x01) != 0 && (transformFlags & 0x02) != 0)
                    {
                        MainThreadManager.Run(() =>
                        {
                            transform.position = ObjectMapper.Instance.Map <Vector3>(metadataTransform);
                            transform.rotation = ObjectMapper.Instance.Map <Quaternion>(metadataTransform);
                        });
                    }
                    else if ((transformFlags & 0x01) != 0)
                    {
                        MainThreadManager.Run(() => { transform.position = ObjectMapper.Instance.Map <Vector3>(metadataTransform); });
                    }
                    else if ((transformFlags & 0x02) != 0)
                    {
                        MainThreadManager.Run(() => { transform.rotation = ObjectMapper.Instance.Map <Quaternion>(metadataTransform); });
                    }
                }
            }

            MainThreadManager.Run(() =>
            {
                NetworkStart();
                networkObject.Networker.FlushCreateActions(networkObject);
            });
        }
        protected override void ReadDirtyFields(BMSByte data, ulong timestep)
        {
            if (readDirtyFlags == null)
            {
                Initialize();
            }

            Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length);
            data.MoveStartIndex(readDirtyFlags.Length);

            if ((0x1 & readDirtyFlags[0]) != 0)
            {
                if (destNetwIdInterpolation.Enabled)
                {
                    destNetwIdInterpolation.target   = UnityObjectMapper.Instance.Map <uint>(data);
                    destNetwIdInterpolation.Timestep = timestep;
                }
                else
                {
                    _destNetwId = UnityObjectMapper.Instance.Map <uint>(data);
                    RunChange_destNetwId(timestep);
                }
            }
            if ((0x2 & readDirtyFlags[0]) != 0)
            {
                if (avatorNetDimsInterpolation.Enabled)
                {
                    avatorNetDimsInterpolation.target   = UnityObjectMapper.Instance.Map <Vector3>(data);
                    avatorNetDimsInterpolation.Timestep = timestep;
                }
                else
                {
                    _avatorNetDims = UnityObjectMapper.Instance.Map <Vector3>(data);
                    RunChange_avatorNetDims(timestep);
                }
            }
            if ((0x4 & readDirtyFlags[0]) != 0)
            {
                if (avatorNetSpeedInterpolation.Enabled)
                {
                    avatorNetSpeedInterpolation.target   = UnityObjectMapper.Instance.Map <float>(data);
                    avatorNetSpeedInterpolation.Timestep = timestep;
                }
                else
                {
                    _avatorNetSpeed = UnityObjectMapper.Instance.Map <float>(data);
                    RunChange_avatorNetSpeed(timestep);
                }
            }
            if ((0x8 & readDirtyFlags[0]) != 0)
            {
                if (avatorNetDestDistanceInterpolation.Enabled)
                {
                    avatorNetDestDistanceInterpolation.target   = UnityObjectMapper.Instance.Map <float>(data);
                    avatorNetDestDistanceInterpolation.Timestep = timestep;
                }
                else
                {
                    _avatorNetDestDistance = UnityObjectMapper.Instance.Map <float>(data);
                    RunChange_avatorNetDestDistance(timestep);
                }
            }
        }
        protected override void ReadDirtyFields(BMSByte data, ulong timestep)
        {
            if (readDirtyFlags == null)
            {
                Initialize();
            }

            Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length);
            data.MoveStartIndex(readDirtyFlags.Length);

            if ((0x1 & readDirtyFlags[0]) != 0)
            {
                if (team0ScoreInterpolation.Enabled)
                {
                    team0ScoreInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    team0ScoreInterpolation.Timestep = timestep;
                }
                else
                {
                    _team0Score = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_team0Score(timestep);
                }
            }
            if ((0x2 & readDirtyFlags[0]) != 0)
            {
                if (team1ScoreInterpolation.Enabled)
                {
                    team1ScoreInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    team1ScoreInterpolation.Timestep = timestep;
                }
                else
                {
                    _team1Score = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_team1Score(timestep);
                }
            }
            if ((0x4 & readDirtyFlags[0]) != 0)
            {
                if (timerInterpolation.Enabled)
                {
                    timerInterpolation.target   = UnityObjectMapper.Instance.Map <float>(data);
                    timerInterpolation.Timestep = timestep;
                }
                else
                {
                    _timer = UnityObjectMapper.Instance.Map <float>(data);
                    RunChange_timer(timestep);
                }
            }
            if ((0x8 & readDirtyFlags[0]) != 0)
            {
                if (originalTimerInterpolation.Enabled)
                {
                    originalTimerInterpolation.target   = UnityObjectMapper.Instance.Map <float>(data);
                    originalTimerInterpolation.Timestep = timestep;
                }
                else
                {
                    _originalTimer = UnityObjectMapper.Instance.Map <float>(data);
                    RunChange_originalTimer(timestep);
                }
            }
        }
        protected override void ReadDirtyFields(BMSByte data, ulong timestep)
        {
            if (readDirtyFlags == null)
            {
                Initialize();
            }

            Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length);
            data.MoveStartIndex(readDirtyFlags.Length);

            if ((0x1 & readDirtyFlags[0]) != 0)
            {
                if (positionInterpolation.Enabled)
                {
                    positionInterpolation.target   = UnityObjectMapper.Instance.Map <Vector2>(data);
                    positionInterpolation.Timestep = timestep;
                }
                else
                {
                    _position = UnityObjectMapper.Instance.Map <Vector2>(data);
                    RunChange_position(timestep);
                }
            }
            if ((0x2 & readDirtyFlags[0]) != 0)
            {
                if (rotationInterpolation.Enabled)
                {
                    rotationInterpolation.target   = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    rotationInterpolation.Timestep = timestep;
                }
                else
                {
                    _rotation = UnityObjectMapper.Instance.Map <Quaternion>(data);
                    RunChange_rotation(timestep);
                }
            }
            if ((0x4 & readDirtyFlags[0]) != 0)
            {
                if (speedInterpolation.Enabled)
                {
                    speedInterpolation.target   = UnityObjectMapper.Instance.Map <float>(data);
                    speedInterpolation.Timestep = timestep;
                }
                else
                {
                    _speed = UnityObjectMapper.Instance.Map <float>(data);
                    RunChange_speed(timestep);
                }
            }
            if ((0x8 & readDirtyFlags[0]) != 0)
            {
                if (damageInterpolation.Enabled)
                {
                    damageInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    damageInterpolation.Timestep = timestep;
                }
                else
                {
                    _damage = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_damage(timestep);
                }
            }
            if ((0x10 & readDirtyFlags[0]) != 0)
            {
                if (ownerNumInterpolation.Enabled)
                {
                    ownerNumInterpolation.target   = UnityObjectMapper.Instance.Map <int>(data);
                    ownerNumInterpolation.Timestep = timestep;
                }
                else
                {
                    _ownerNum = UnityObjectMapper.Instance.Map <int>(data);
                    RunChange_ownerNum(timestep);
                }
            }
        }