Esempio n. 1
0
        public override void Load()
        {
            Everest.Events.Input.OnInitialize += OnInputInitialize;
            Everest.Events.Input.OnDeregister += OnInputDeregister;

            GhostNetHooks.Load();

            // Example of a MP server mod.
            GhostNetServer.OnCreate += GhostNetRaceManager.OnCreateServer;

            base.Initialize();

            Queue <string> args = new Queue <string>(Everest.Args);

            while (args.Count > 0)
            {
                string arg = args.Dequeue();
                if (arg == "--server")
                {
                    _StartServer = true;
                }
                else if (arg == "--headless")
                {
                    _StartHeadless = true;
                }
            }

            GhostModule.SettingsOverridden = true;
            ResetGhostModuleSettings();

            if (_StartServer && _StartHeadless)
            {
                // We don't care about other mods.
                GhostNetFrame.RegisterChunksFromModule(this);

                Start(true, true);
                RunDedicated();
                Environment.Exit(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;
                }
            }
Esempio n. 3
0
 public ChunkMChat CreateMChat(GhostNetFrame frame, string text, string tag = null, Color?color = null, bool fillVars = false, uint?id = null)
 {
     lock (ChatLog) {
         ChunkMChat chunk = new ChunkMChat {
             ID              = id ?? (uint)ChatLog.Count,
             Text            = fillVars ? FillVariables(text, frame) : text,
             Tag             = tag ?? "",
             Color           = color ?? GhostNetModule.Settings.ServerColorDefault,
             Date            = DateTime.UtcNow,
             CreatedByServer = true,
             Logged          = true
         };
         if (id == null)
         {
             ChatLog.Add(chunk);
         }
         else
         {
             ChatLog[(int)id] = chunk;
         }
         return(chunk);
     }
 }
Esempio n. 4
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);
            }
 public override void SendUpdate(GhostNetFrame frame, IPEndPoint remote, bool release)
 {
     throw new NotSupportedException("Local connections don't support sending updates to another client.");
 }
 public override void SendUpdate(GhostNetFrame frame, bool release)
 {
     ReceiveUpdate(UpdateEndPoint, (GhostNetFrame)frame.Clone());
 }
 public override void SendManagement(GhostNetFrame frame, bool release)
 {
     ReceiveManagement(ManagementEndPoint, (GhostNetFrame)frame.Clone());
 }
 public override void SendManagement(GhostNetFrame frame, bool release)
 {
     lock (ManagementQueue) {
         ManagementQueue.Enqueue(Tuple.Create(frame, release));
     }
 }
Esempio n. 9
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);
        }
Esempio n. 10
0
        protected virtual void HandleU(GhostNetConnection conReceived, IPEndPoint remote, GhostNetFrame frame)
        {
            // Prevent UpdateConnection locking in on a single player.
            if (conReceived == UpdateConnection)
            {
                UpdateConnection.UpdateEndPoint = null;
            }

            GhostNetConnection con;

            // We receive updates either from LocalConnectionToServer or from UpdateConnection.
            // Get the managed connection to the remote client.
            if (conReceived == null || !ConnectionMap.TryGetValue(remote, out con) || con == null)
            {
                // Unlike management connections, which we already know the target port of at the time of connection,
                // updates are sent via UDP (by default) and thus "connectionless."
                // If we've got a queued connection for that address, update it.
                GhostNetConnection queue;
                if (UpdateConnectionQueue.TryGetValue(remote.Address, out queue) && queue != null)
                {
                    con = queue;
                    con.UpdateEndPoint = remote;
                    ConnectionMap[con.UpdateEndPoint] = con;
                    Logger.Log(LogLevel.Verbose, "ghostnet-s", $"Mapped update connection ({con.ManagementEndPoint}, {con.UpdateEndPoint})");
                }
                else
                {
                    // If the address is completely unknown, drop the frame.
                    Logger.Log(LogLevel.Verbose, "ghostnet-s", $"Unknown update from {remote} - unknown connection, possibly premature");
                    return;
                }
            }

            Handle(con, frame);
        }
Esempio n. 11
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;
        }
Esempio n. 12
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);
            }
        }
Esempio n. 13
0
        public void EndKevinballMatch(uint winner, uint loser, uint wintype)
        {
            ActiveKevinballMatch    = false;
            LastKevinballWinner     = winner;
            LastKevinballLoser      = loser;
            KevinballScores[winner] = new Vector2(KevinballScores[winner].X + 1, KevinballScores[winner].Y);
            KevinballScores[loser]  = new Vector2(KevinballScores[loser].X, KevinballScores[loser].Y + 1);

            if (!PlayerMap.ContainsKey(winner))
            {
                return;
            }

            string finalString = PlayerMap[winner].Name + " wins!";

            if (wintype == GhostNetClient.KevinballWin)
            {
                finalString = finalString + " GOOOOAAAAALLLL!!";
            }
            else if (wintype == GhostNetClient.CoinWin)
            {
                finalString = finalString + " Coin victory!";
            }
            else if (wintype == GhostNetClient.DeathWin)
            {
                finalString = finalString + " Survival victory!";
            }

            BroadcastMChat(new GhostNetFrame
            {
                HHead = new ChunkHHead
                {
                    PlayerID = uint.MaxValue
                }
            }, finalString);

            GhostNetFrame frame = new GhostNetFrame
            {
                HHead = new ChunkHHead
                {
                    PlayerID = uint.MaxValue
                }
            };

            bool shouldShuffle = false;

            if (ShuffleMode > 0)
            {
                foreach (KeyValuePair <uint, Vector2> kvp in KevinballScores)
                {
                    if (kvp.Value.X >= ShuffleMode)
                    {
                        shouldShuffle = true;
                        string name = PlayerMap[kvp.Key].Name;
                        string str  = name + " wins the map! Shuffling maps...";
                        BroadcastMChat(new GhostNetFrame
                        {
                            HHead = new ChunkHHead
                            {
                                PlayerID = uint.MaxValue
                            }
                        }, str);
                    }
                }

                if (shouldShuffle == true)
                {
                    CurrentKevinballLevel = CurrentKevinballLevel + 1;
                    justShuffled          = true;
                }
            }

            if (shouldShuffle)
            {
                List <uint> keys = KevinballScores.Keys.ToList();
                foreach (uint key in keys)
                {
                    KevinballScores[key] = new Vector2(0, 0);
                }
            }

            ChunkMKevinballEnd chunk = new ChunkMKevinballEnd
            {
                Winner    = winner,
                Wintype   = wintype,
                NextLevel = CurrentKevinballLevel
            };

            frame.Add(chunk);
            PropagateM(frame);
        }
Esempio n. 14
0
 public string FillVariables(string input, GhostNetFrame frame)
 => input
 .Replace("((player))", frame.MPlayer.Name)
 .Replace("((id))", frame.HHead.PlayerID.ToString())
 .Replace("((server))", GhostNetModule.Settings.ServerNameAuto);
Esempio n. 15
0
 public abstract void SendUpdate(GhostNetFrame frame, IPEndPoint remote, bool release);
Esempio n. 16
0
 public abstract void SendUpdate(GhostNetFrame frame, bool release, bool log = false);
Esempio n. 17
0
 public abstract void SendManagement(GhostNetFrame frame, bool release);
Esempio n. 18
0
        public void RunKevinballMatch()
        {
            if (KevinballPlayerIDs.Count < 2)
            {
                return;
            }

            if (ActiveKevinballMatch)
            {
                return;
            }

            uint player1 = KevinballP1;
            uint player2 = KevinballP2;

            ActiveKevinballMatch = true;

            if (!PlayerMap.ContainsKey(player1) || !PlayerMap.ContainsKey(player2) || !KevinballScores.ContainsKey(player1) || !KevinballScores.ContainsKey(player2))
            {
                return;
            }

            string p1Name  = PlayerMap[player1].Name;
            string p2Name  = PlayerMap[player2].Name;
            string p1Score = KevinballScores[player1].X.ToString() + " - " + KevinballScores[player1].Y.ToString();
            string p2Score = KevinballScores[player2].X.ToString() + " - " + KevinballScores[player2].Y.ToString();
            //BroadcastMChat(new GhostNetFrame
            //{
            //    HHead = new ChunkHHead
            //    {
            //        PlayerID = uint.MaxValue;
            //},
            //}, "Starting Kevinball!" + p1Name + " [" + p1Score + "] vs. " + p2Name + " [" + p2Score + "]");

            string finalString = "Starting Kevinball! " + p1Name + " [" + p1Score + "] vs. " + p2Name + " [" + p2Score + "]";

            BroadcastMChat(new GhostNetFrame
            {
                HHead = new ChunkHHead
                {
                    PlayerID = uint.MaxValue
                }
            }, finalString);

            GhostNetFrame frame = new GhostNetFrame
            {
                HHead = new ChunkHHead
                {
                    PlayerID = uint.MaxValue
                }
            };

            ChunkMKevinballStart chunk = new ChunkMKevinballStart
            {
                Player1 = player1,
                Player2 = player2
            };

            frame.Add(chunk);
            PropagateM(frame);


            //Send Kevinball start chunk with both player ids
        }