示例#1
0
            public void Move(uint playerID, int index, GhostNetFrame frame = null)
            {
                Logger.Log(LogLevel.Verbose, "ghostnet-race", $"Moving player {playerID} to index {index}");
                GhostNetConnection con = Manager.Server.Connections[(int)playerID];
                ChunkMPlayer       playerCached;

                if (con == null || !Manager.Server.PlayerMap.TryGetValue(playerID, out playerCached) || playerCached == null)
                {
                    return;
                }
                Indices[playerID] = index;
                if (index == -1 && WaitingForStart.Contains(playerID) && string.IsNullOrEmpty(playerCached.SID))
                {
                    WaitingForStart.Remove(playerID);
                    return;
                }

                ChunkMPlayer player = new ChunkMPlayer {
                    Name  = playerCached.Name,
                    SID   = index == -1 ? "" : Areas[index].Item1,
                    Mode  = index == -1 ? AreaMode.Normal : Areas[index].Item2,
                    Level = ""
                };

                if (frame == null)
                {
                    con.SendManagement(new GhostNetFrame {
                        HHead = new ChunkHHead {
                            PlayerID = playerID
                        },

                        MPlayer = player
                    }, true);
                }
                else
                {
                    frame.MPlayer    = player;
                    frame.PropagateM = true;
                }
            }
示例#2
0
        public virtual void HandleULoadedKevinball(GhostNetConnection con, GhostNetFrame frame)
        {
            ChunkULoadedKevinball press = frame;

            ChunkMPlayer otherPlayer;

            if (!PlayerMap.TryGetValue(press.With, out otherPlayer) || otherPlayer == null ||
                frame.MPlayer.SID != otherPlayer.SID ||
                frame.MPlayer.Mode != otherPlayer.Mode
                )
            {
                // Player not in the same room.
                return;
            }

            if (!KevinballPlayerIDs.Contains(press.With))
            {
                KevinballPlayerIDs.Add(press.With);
                KevinballQueue.Add(press.With);

                //TESTING
                //KevinballPlayerIDs.Add(press.With);
                //KevinballQueue.Add(press.With);
            }

            if (!KevinballScores.ContainsKey(press.With))
            {
                KevinballScores.Add(press.With, new Vector2(0, 0));
            }

            if (ActiveKevinballMatch)
            {
                return;
            }

            if (KevinballPlayerIDs.Count - SpectatingPlayers.Count >= 2)
            {
                StartKevinball(con, frame);
            }
        }
示例#3
0
            public ChunkMChat Send(GhostNetFrame frame, string text, string tag = "race", Color?color = null, bool fillVars = false, uint?id = null)
            {
                ChunkMChat    msg      = Manager.Server.CreateMChat(frame, text, tag, color ?? (frame != null ? ColorDefault : ColorBroadcast), fillVars, id);
                GhostNetFrame frameMsg = new GhostNetFrame {
                    frame?.HHead ?? new ChunkHHead {
                        PlayerID = uint.MaxValue
                    },
                    msg
                };

                lock (Players) {
                    foreach (uint playerID in Players)
                    {
                        GhostNetConnection con = Manager.Server.Connections[(int)playerID];
                        if (con == null)
                        {
                            continue;
                        }
                        con.SendManagement(frameMsg, false);
                    }
                }
                return(msg);
            }
示例#4
0
        public virtual void Accept(GhostNetConnection con)
        {
            uint id = (uint)Connections.Count;

            Logger.Log(LogLevel.Verbose, "ghostnet-s", $"Client #{id} ({con.ManagementEndPoint}) accepted");
            Connections.Add(con);
            ConnectionMap[con.ManagementEndPoint] = con;
            UpdateConnectionQueue[con.ManagementEndPoint.Address] = con;
            if (GhostNetModule.Settings.ServerRemoteOpIPs.Contains(con.ManagementEndPoint.Address.ToString()))
            {
                OPs.Add(id);
            }
            con.SendManagement(new GhostNetFrame {
                new ChunkHHead {
                    PlayerID = id
                },
                new ChunkMServerInfo {
                    Name = GhostNetModule.Settings.ServerNameAuto
                },
                new ChunkMRequest {
                    ID = ChunkMPlayer.ChunkID
                }
            }, true);
        }
示例#5
0
        protected virtual void HandleDisconnect(GhostNetConnection con)
        {
            if (con == null)
            {
                return; // Probably already disconnected.
            }
            uint id = (uint)Connections.IndexOf(con);

            if (id == uint.MaxValue)
            {
                Logger.Log(LogLevel.Verbose, "ghostnet-s", $"Client #? ({con.ManagementEndPoint}) disconnected?");
                return;
            }
            Logger.Log(LogLevel.Verbose, "ghostnet-s", $"Client #{id} ({con.ManagementEndPoint}) disconnected");

            Connections[(int)id] = null;

            ConnectionMap[con.ManagementEndPoint] = null;

            if (con.UpdateEndPoint != null)
            {
                ConnectionMap[con.UpdateEndPoint] = null;
            }
            else
            {
                UpdateConnectionQueue[con.ManagementEndPoint.Address] = null;
            }

            ChunkMPlayer player;

            if (PlayerMap.TryGetValue(id, out player) && player != null &&
                !string.IsNullOrWhiteSpace(player.Name) &&
                !string.IsNullOrWhiteSpace(GhostNetModule.Settings.ServerMessageLeave))
            {
                BroadcastMChat(new GhostNetFrame {
                    HHead = new ChunkHHead {
                        PlayerID = id
                    },

                    MPlayer = player
                }, GhostNetModule.Settings.ServerMessageLeave, fillVars: true);
            }

            OnDisconnect?.Invoke(id, player);

            // Propagate disconnect to all other players.
            GhostNetFrame frame = new GhostNetFrame {
                HHead = new ChunkHHead {
                    PlayerID = id
                },

                MPlayer = new ChunkMPlayer {
                    Name  = "",
                    SID   = "",
                    Mode  = AreaMode.Normal,
                    Level = ""
                }
            };

            lock (PlayerMap) {
                PlayerMap[id] = null;
            }
            PropagateM(frame);
        }
示例#6
0
        public virtual void HandleMChat(GhostNetConnection con, GhostNetFrame frame)
        {
            ChunkMChat msg = frame;

            msg.Text = msg.Text.TrimEnd();
            // Logger.Log(LogLevel.Info, "ghostnet-s", $"#{frame.HHead.PlayerID} said: {frame.MChat.Text}");

            if (!msg.Logged)
            {
                lock (ChatLog) {
                    msg.ID = (uint)ChatLog.Count;
                    ChatLog.Add(msg);
                }
            }

            // Handle commands if necessary.
            if (msg.Text.StartsWith(GhostNetModule.Settings.ServerCommandPrefix))
            {
                // Echo the chat chunk separately.
                msg.Color = GhostNetModule.Settings.ServerColorCommand;
                con.SendManagement(new GhostNetFrame {
                    frame.HHead,
                    msg
                }, true);

                GhostNetCommandEnv env = new GhostNetCommandEnv {
                    Server     = this,
                    Connection = con,
                    Frame      = frame
                };

                string prefix = GhostNetModule.Settings.ServerCommandPrefix;

                // TODO: This is basically a port of disbot-neo's Handler.

                string cmdName = env.Text.Substring(prefix.Length);
                cmdName = cmdName.Split(GhostNetCommand.CommandNameDelimiters)[0].ToLowerInvariant();
                if (cmdName.Length == 0)
                {
                    return;
                }

                GhostNetCommand cmd = GetCommand(cmdName);
                if (cmd != null)
                {
                    GhostNetFrame cmdFrame = frame;
                    Task.Run(() => {
                        try {
                            cmd.Parse(env);
                        } catch (Exception e) {
                            SendMChat(con, cmdFrame, $"Command {cmdName} failed: {e.Message}", color: GhostNetModule.Settings.ServerColorError, fillVars: false);
                            if (e.GetType() != typeof(Exception))
                            {
                                Logger.Log(LogLevel.Warn, "ghostnet-s", $"cmd failed: {env.Text}");
                                e.LogDetailed();
                            }
                        }
                    });
                }
                else
                {
                    SendMChat(con, frame, $"Command {cmdName} not found!", color: GhostNetModule.Settings.ServerColorError, fillVars: false);
                }

                return;
            }

            if (!msg.CreatedByServer)
            {
                msg.Text.Replace("\r", "").Replace("\n", "");
                if (msg.Text.Length > GhostNetModule.Settings.ServerMaxChatTextLength)
                {
                    msg.Text = msg.Text.Substring(0, GhostNetModule.Settings.ServerMaxChatTextLength);
                }

                msg.Tag   = "";
                msg.Color = Color.White;
            }

            msg.Date = DateTime.UtcNow;

            frame.PropagateM = true;
        }
示例#7
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);
            }
        }
示例#8
0
 public GhostNetFrame Request <T>(GhostNetConnection con, long timeout = 5000) where T : IChunk
 => Request(typeof(T), con, timeout);