Exemplo n.º 1
0
        public virtual void Handle(GhostNetConnection con, GhostNetFrame frame)
        {
            SetNetHead(con, frame);

            if (frame.HHead == null)
            {
                return;
            }

            bool lockedMPlayer = false;

            if (frame.MPlayer != null)
            {
                Monitor.Enter(frame.MPlayer, ref lockedMPlayer);
                frame.MPlayer.IsCached = false;
                HandleMPlayer(con, frame);
            }

            ChunkMPlayer player;

            if (!PlayerMap.TryGetValue(frame.HHead.PlayerID, out player) || player == null)
            {
                // Ghost not managed - ignore the frame.
                Logger.Log(LogLevel.Verbose, "ghostnet-s", $"Unexpected frame from #{frame.HHead?.PlayerID.ToString() ?? "???"} ({con.ManagementEndPoint}) - no MPlayer on this connection, possibly premature");
                return;
            }
            // Temporarily attach the MPlayer chunk to make player identification easier.
            if (frame.MPlayer == null)
            {
                frame.MPlayer = player;
                Monitor.Enter(frame.MPlayer, ref lockedMPlayer);
                frame.MPlayer.IsCached = true;
            }

            if (frame.Has <ChunkMRequest>())
            {
                // TODO: Handle requests by client in server.

                frame.Remove <ChunkMRequest>(); // Prevent request from being propagated.
            }

            if (frame.Has <ChunkMEmote>())
            {
                HandleMEmote(con, frame);
            }

            if (frame.Has <ChunkMChat>())
            {
                HandleMChat(con, frame);
            }

            if (frame.UUpdate != null)
            {
                HandleUUpdate(con, frame);
            }

            if (frame.Has <ChunkUActionCollision>())
            {
                HandleUActionCollision(con, frame);
            }

            // TODO: Restrict players from abusing UAudioPlay and UParticles propagation.
            if (frame.Has <ChunkUAudioPlay>())
            {
                // Propagate audio to all active players in the same room.
                frame.PropagateU = true;
            }

            if (frame.Has <ChunkUParticles>())
            {
                // Propagate particles to all active players in the same room.
                frame.PropagateU = true;
            }

            OnHandle?.Invoke(con, frame);

            if (frame.PropagateM)
            {
                PropagateM(frame);
            }
            else if (frame.PropagateU)
            {
                PropagateU(frame);
            }

            if (lockedMPlayer)
            {
                Monitor.Exit(frame.MPlayer);
            }
        }