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());
        }
示例#2
0
 public override void Parse(GhostNetCommandEnv env)
 {
     if (OnParse != null)
     {
         OnParse(this, env);
         return;
     }
     base.Parse(env);
 }
        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));
        }
        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());
        }
        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 virtual void Parse(GhostNetCommandEnv env)
        {
            string raw = env.Text;

            int index = GhostNetModule.Settings.ServerCommandPrefix.Length + Name.Length - 1; // - 1 because next space required
            List <GhostNetCommandArg> args = new List <GhostNetCommandArg>();

            while (
                index + 1 < raw.Length &&
                (index = raw.IndexOf(' ', index + 1)) >= 0
                )
            {
                int next = index + 1 < raw.Length ? raw.IndexOf(' ', index + 1) : -2;
                if (next < 0)
                {
                    next = raw.Length;
                }

                int    argIndex  = index + 1;
                int    argLength = next - index - 1;
                string argString = raw.Substring(argIndex, argLength);

                // + 1 because space
                args.Add(new GhostNetCommandArg(env).Parse(raw, argIndex, argLength));

                // Parse a range
                if (args.Count >= 3 &&
                    args[args.Count - 3].Type == GhostNetCommandArg.EType.Int &&
                    (args[args.Count - 2].String == "-" || args[args.Count - 2].String == "+") &&
                    args[args.Count - 1].Type == GhostNetCommandArg.EType.Int
                    )
                {
                    args.Add(new GhostNetCommandArg(env).Parse(raw, args[args.Count - 3].Index, next - args[args.Count - 3].Index));
                    args.RemoveRange(args.Count - 4, 3);
                    continue;
                }
            }

            Run(env, args.ToArray());
        }
示例#7
0
 public virtual void Run(GhostNetCommandEnv env, params GhostNetCommandArg[] args)
 {
 }
示例#8
0
 public GhostNetCommandArg(GhostNetCommandEnv env)
 {
     Env = env;
 }
示例#9
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));
示例#10
0
 public override void Run(GhostNetCommandEnv env, params GhostNetCommandArg[] args)
 => OnRun(this, env, args);
示例#11
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]}!");
            }
        }
示例#12
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;
        }