public static string Help_GetCommandPage(GhostNetCommandEnv env, int page = 0)
        {
            const int pageSize = 8;

            string        prefix  = GhostNetModule.Settings.ServerCommandPrefix;
            StringBuilder builder = new StringBuilder();

            int pages = (int)Math.Ceiling(env.Server.Commands.Count / (float)pageSize);

            if (page < 0 || pages <= page)
            {
                throw new Exception("Page out of range!");
            }

            for (int i = page * pageSize; i < (page + 1) * pageSize && i < env.Server.Commands.Count; i++)
            {
                GhostNetCommand cmd = env.Server.Commands[i];
                builder
                .Append(prefix)
                .Append(cmd.Name)
                .Append(" ")
                .Append(cmd.Args)
                .AppendLine();
            }

            builder
            .Append("Page ")
            .Append(page + 1)
            .Append("/")
            .Append(pages);

            return(builder.ToString().Trim());
        }
        public static string Help_GetCommandSnippet(GhostNetCommandEnv env, string cmdName)
        {
            GhostNetCommand cmd = env.Server.GetCommand(cmdName);

            if (cmd == null)
            {
                throw new Exception($"Command {cmdName} not found!");
            }

            return(Help_GetCommandSnippet(env, cmd));
        }
예제 #3
0
 public GhostNetCommand GetCommand(string cmdName)
 {
     cmdName = cmdName.ToLowerInvariant();
     for (int i = 0; i < Commands.Count; i++)
     {
         GhostNetCommand cmd = Commands[i];
         if (cmd.Name == cmdName)
         {
             return(cmd);
         }
     }
     return(null);
 }
        public static string Help_GetCommandSnippet(GhostNetCommandEnv env, GhostNetCommand cmd)
        {
            string        prefix  = GhostNetModule.Settings.ServerCommandPrefix;
            StringBuilder builder = new StringBuilder();

            builder
            .Append(prefix)
            .Append(cmd.Name)
            .Append(" ")
            .Append(cmd.Args)
            .AppendLine()
            .AppendLine(cmd.Help);

            return(builder.ToString().Trim());
        }
예제 #5
0
        protected virtual void RunCommandRaceChat(GhostNetCommand cmd, GhostNetCommandEnv env, GhostNetCommandArg[] args)
        {
            if (args.Length == 0 || string.IsNullOrWhiteSpace(args[0]))
            {
                return;
            }

            Race race = GetRace(env.PlayerID);

            if (race == null)
            {
                throw new Exception($"You're not in a race!");
            }

            race.Send(env.Frame, args[0], id: env.MChat.ID);
        }
예제 #6
0
 public void RegisterCommandsFromModule(EverestModule module)
 {
     foreach (Type type in module.GetType().Assembly.GetTypes())
     {
         foreach (FieldInfo field in type.GetFields(BindingFlags.Public | BindingFlags.Static))
         {
             if (!typeof(GhostNetCommand).IsAssignableFrom(field.FieldType) ||
                 field.GetCustomAttribute <GhostNetCommandFieldAttribute>() == null)
             {
                 continue;
             }
             GhostNetCommand cmd = field.GetValue(null) as GhostNetCommand;
             if (cmd == null)
             {
                 continue;
             }
             Commands.Add(cmd);
         }
     }
 }
예제 #7
0
 /// <summary>
 /// Parse everything as one argument and run the command.
 /// </summary>
 public static void Everything(GhostNetCommand cmd, GhostNetCommandEnv env)
 => cmd.Run(env, new GhostNetCommandArg(env).Parse(env.Text, GhostNetModule.Settings.ServerCommandPrefix.Length + cmd.Name.Length + 1));
예제 #8
0
        protected virtual void RunCommandRace(GhostNetCommand cmd, GhostNetCommandEnv env, GhostNetCommandArg[] args)
        {
            if (args.Length == 0)
            {
                GhostNetCommandsStandard.Help.Run(env, new GhostNetCommandArg(env).Parse(cmd.Name, 0));
                return;
            }

            Race race;

            switch (args[0])
            {
            case "add":
            case "+":
                race = GetRace(env.PlayerID);
                if (race != null && race.Players[0] != env.PlayerID)
                {
                    throw new Exception("You don't own the race!");
                }
                if (race == null)
                {
                    race = GetOrCreateRace(env.PlayerID);
                    env.Send($"New race created: #{race.ID + 1}");
                }

                if (race.HasStarted)
                {
                    throw new Exception("The race has already started!");
                }

                if (args.Length == 1)
                {
                    // Add the area the player currently is in.
                    if (string.IsNullOrEmpty(env.MPlayer.SID))
                    {
                        throw new Exception("You can't add the menu to the race!");
                    }
                    lock (race.Areas) {
                        race.Areas.Add(Tuple.Create(env.MPlayer.SID, env.MPlayer.Mode));
                    }
                }
                else if (args.Length < 3)
                {
                    throw new Exception("Not enough arguments!");
                }
                else if (args.Length > 3)
                {
                    throw new Exception("Too many arguments!");
                }
                else
                {
                    int mode = -1;
                    if (args[2].Type == GhostNetCommandArg.EType.Int)
                    {
                        mode = args[2].Int - 1;
                    }
                    else if (args[2].String.Length == 1)
                    {
                        mode = args[2].String.ToLowerInvariant()[0] - 'a';
                    }
                    if (mode < 0 || 2 < mode)
                    {
                        throw new Exception("Mode must be one of the following: a 1 b 2 c 3");
                    }

                    string area = args[1].String;
                    if (args[1].Type == GhostNetCommandArg.EType.Int)
                    {
                        ChunkRListAreas areas;
                        env.Server.Request(env.Connection, out areas);
                        if (areas == null)
                        {
                            throw new Exception("Your client didn't respond to the area list request!");
                        }
                        if (args[1].Int < 1 || areas.Entries.Length < args[1].Int)
                        {
                            throw new Exception("Not a valid ID!");
                        }
                        area = areas.Entries[args[1].Int - 1];
                    }

                    lock (race.Areas) {
                        race.Areas.Add(Tuple.Create(area, (AreaMode)mode));
                    }
                }

                env.Send(race.AreaList);
                return;

            case "remove":
            case "-":
                race = GetRace(env.PlayerID);
                if (race == null)
                {
                    throw new Exception($"You're not in a race!");
                }
                if (race.Players[0] != env.PlayerID)
                {
                    throw new Exception("You don't own the race!");
                }
                if (race.HasStarted)
                {
                    throw new Exception("The race has already started!");
                }

                if (args.Length < 2)
                {
                    throw new Exception("Not enough arguments!");
                }
                if (args.Length > 2)
                {
                    throw new Exception("Too many arguments!");
                }

                lock (race.Areas) {
                    if (args[1].Type != GhostNetCommandArg.EType.Int ||
                        args[1].Int < 1 || race.Areas.Count < args[1].Int)
                    {
                        throw new Exception("Not a valid ID!");
                    }

                    race.Areas.RemoveAt(args[1].Int - 1);
                }

                env.Send(race.AreaList);
                return;

            case "start":
                if (args.Length > 1)
                {
                    throw new Exception("Too many arguments!");
                }

                race = GetRace(env.PlayerID);
                if (race == null)
                {
                    throw new Exception($"You're not in a race!");
                }
                if (race.Players[0] != env.PlayerID)
                {
                    throw new Exception("You don't own the race!");
                }

                race.Start();
                return;

            case "join":
                race = GetRace(env.PlayerID);
                if (race != null)
                {
                    throw new Exception($"You're already in race #{race.ID}!");
                }

                if (args.Length < 2)
                {
                    throw new Exception("Not enough arguments!");
                }
                if (args.Length > 2)
                {
                    throw new Exception("Too many arguments!");
                }

                if (args[1].Type != GhostNetCommandArg.EType.Int ||
                    args[1].Int < 1 || Races.Count < args[1].Int)
                {
                    throw new Exception("Not a valid ID!");
                }
                race = Races[args[1].Int - 1];
                if (race == null)
                {
                    throw new Exception("The race has already ended!");
                }

                if (race.HasStarted)
                {
                    throw new Exception("You're too late, the race has already started without you!");
                }

                lock (race.Players) {
                    race.Players.Add(env.PlayerID);
                }
                race.Send(null, $"{env.MPlayer.Name}#{env.HHead.PlayerID} joined.");
                return;

            case "leave":
                if (args.Length > 1)
                {
                    throw new Exception("Too many arguments!");
                }

                race = GetRace(env.PlayerID);
                if (race == null)
                {
                    throw new Exception($"You're not in a race!");
                }

                race.RemovePlayer(env.PlayerID, $"{env.MPlayer.Name}#{env.HHead.PlayerID} left.");
                return;

            case "list":
                if (args.Length > 1)
                {
                    throw new Exception("Too many arguments!");
                }

                race = GetRace(env.PlayerID);
                StringBuilder builder = new StringBuilder();
                int           count   = 0;
                lock (Races) {
                    for (int i = 0; i < Races.Count; i++)
                    {
                        Race raceListed = Races[i];
                        if (raceListed == null)
                        {
                            continue;
                        }
                        ChunkMPlayer owner;
                        string       ownerName = null;
                        if (env.Server.PlayerMap.TryGetValue(raceListed.Players[0], out owner) && owner != null)
                        {
                            ownerName = owner.Name;
                        }
                        builder
                        .Append(race == raceListed ? '>' : raceListed.HasStarted ? 'X' : '#')
                        .Append(raceListed.ID + 1)
                        .Append(" by ")
                        .Append(string.IsNullOrEmpty(ownerName) ? "???" : ownerName)
                        .AppendLine();
                        count++;
                    }
                }
                builder.Append(count).Append(" race");
                if (count != 1)
                {
                    builder.Append('s');
                }
                env.Send(builder.ToString().Trim());
                return;

            case "areas":
            case "players":
                if (args.Length == 1)
                {
                    race = GetRace(env.PlayerID);
                    if (race == null)
                    {
                        throw new Exception($"You're not in a race!");
                    }
                }
                else if (args.Length > 2)
                {
                    throw new Exception("Too many arguments!");
                }
                else if (args[1].Type != GhostNetCommandArg.EType.Int ||
                         args[1].Int <= 0 || Races.Count < args[1].Int)
                {
                    throw new Exception("Not a valid ID!");
                }
                else
                {
                    race = Races[args[1].Int - 1];
                    if (race == null)
                    {
                        throw new Exception("Race already ended!");
                    }
                }

                switch (args[0])
                {
                case "areas":
                    env.Send(race.AreaList);
                    return;

                case "players":
                    env.Send(race.PlayerList);
                    return;

                default:
                    throw new Exception($"Can't list {args[0]}!");
                }

            default:
                throw new Exception($"Unknown subcommand {args[0]}!");
            }
        }
예제 #9
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;
        }