diff --git a/Commands/Information/CmdUnloaded.cs b/Commands/Information/CmdUnloaded.cs index d5a3de2f0..d45a24479 100644 --- a/Commands/Information/CmdUnloaded.cs +++ b/Commands/Information/CmdUnloaded.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.Collections.Generic; using System.IO; using System.Text; @@ -30,59 +31,30 @@ namespace MCGalaxy.Commands { public CmdUnloaded() { } public override void Use(Player p, string message) { - bool all = false; - int start = 0, end = 0; - if (message.CaselessStarts("all")) { - all = true; - int index = message.IndexOf(' '); - message = message.Substring(index == -1 ? message.Length : (index + 1)); - } - if (message != "") { - if (!int.TryParse(message, out end) || end <= 0) { Help(p); return; } - end *= 50; - start = end - 50; - } - string[] files = Directory.GetFiles("levels", "*.lvl"); - if (end == 0) { - StringBuilder list = ListMaps(p, all, files, 0, files.Length); - if (list.Length > 0) { - Player.Message(p, "Unloaded levels (&c[no] %Sif not accessible): "); - Player.Message(p, list.Remove(0, 2).ToString()); - if (files.Length > 50) { Player.Message(p, "For a more structured list, use /unloaded <1/2/3/..>"); } - } else { - Player.Message(p, "No maps are unloaded"); - } - } else { - if (end > files.Length) end = files.Length; - if (start > files.Length) { Player.Message(p, "No maps beyond number " + files.Length); return; } - - StringBuilder list = ListMaps(p, all, files, start, end); - if (list.Length > 0) { - Player.Message(p, "Unloaded levels (&c[no] %Sif not accessible) (" + start + " to " + end + "):"); - Player.Message(p, list.Remove(0, 2).ToString()); - } else { - Player.Message(p, "No maps are unloaded"); - } + Player.Message(p, "Unloaded maps (&c[no] %Sif not accessible): "); + MultiPageOutput.Output(p, GetMaps(files), file => FormatMap(p, file), + "unloaded", "maps", message); + } + + static IEnumerable GetMaps(string[] files) { + foreach (string file in files) { + Level[] loaded = LevelInfo.Loaded.Items; + string level = Path.GetFileNameWithoutExtension(file); + if (IsLoaded(loaded, level)) continue; + yield return level; } } - static StringBuilder ListMaps(Player p, bool all, string[] files, int start, int end) { - StringBuilder builder = new StringBuilder(); - Level[] loaded = LevelInfo.Loaded.Items; - for (int i = start; i < end; i++) { - string level = Path.GetFileNameWithoutExtension(files[i]); - if (!all && IsLoaded(loaded, level)) continue; - - LevelPermission visitP, buildP; - bool loadOnGoto; - RetrieveProps(level, out visitP, out buildP, out loadOnGoto); - - string color = Group.findPerm(buildP).color; - string visit = loadOnGoto && (p == null || p.Rank >= visitP) ? "" : " &c[no]" + color; - builder.Append(", ").Append(color + level + visit); - } - return builder; + static string FormatMap(Player p, string file) { + string level = Path.GetFileNameWithoutExtension(file); + LevelPermission visitP, buildP; + bool loadOnGoto; + RetrieveProps(level, out visitP, out buildP, out loadOnGoto); + + string color = Group.findPerm(buildP).color; + string visit = loadOnGoto && (p == null || p.Rank >= visitP) ? "" : " &c[no]" + color; + return color + level + visit; } static bool IsLoaded(Level[] loaded, string level) { @@ -107,7 +79,7 @@ namespace MCGalaxy.Commands { grp = args.Visit == null ? null : Group.Find(args.Visit); if (grp != null) visit = grp.Permission; grp = args.Build == null ? null : Group.Find(args.Build); - if (grp != null) build = grp.Permission; + if (grp != null) build = grp.Permission; if (!bool.TryParse(args.LoadOnGoto, out loadOnGoto)) loadOnGoto = true; } diff --git a/Commands/other/CmdReport.cs b/Commands/other/CmdReport.cs index 2a094ac24..9efc86fef 100644 --- a/Commands/other/CmdReport.cs +++ b/Commands/other/CmdReport.cs @@ -112,7 +112,7 @@ namespace MCGalaxy.Commands { } void HandleClear(Player p, string[] args) { - if (!CheckExtraPerm(p)) { MessageNeedExtra(p, "clear the list of reports."); return; } + if (!CheckExtraPerm(p)) { MessageNeedExtra(p, "clear the list of reports."); return; } if (!Directory.Exists("extra/reportedbackups")) Directory.CreateDirectory("extra/reportedbackups"); string[] files = Directory.GetFiles("extra/reported", "*.txt"); diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index dc42e38b8..b217e996a 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -610,6 +610,7 @@ + diff --git a/util/MultiPageOutput.cs b/util/MultiPageOutput.cs new file mode 100644 index 000000000..4ebd0621c --- /dev/null +++ b/util/MultiPageOutput.cs @@ -0,0 +1,67 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using System.Collections.Generic; + +namespace MCGalaxy { + + /// Outputs a large range of values across a number of 'pages'. + public static class MultiPageOutput { + + const int perPage = 30; + + public static void Output(Player p, IEnumerable items, Func formatter, + string cmd, string type, string input) { + List all = new List(items); + int page = 0, total = all.Count; + + if (input == "") { + OutputPage(p, all, formatter, cmd, type, 0); + if (total <= perPage) return; + Player.Message(p, "To see all {0}, use %T/{1} all", type, cmd); + } else if (input.CaselessEq("all")) { + Player.Message(p, all.Join(formatter, ", ")); + Player.Message(p, "Showing {0} 1-{1} (out of {1})", type, all.Count); + } else if (!int.TryParse(input, out page)) { + Player.Message(p, "Page must be either \"all\" or an integer."); + } else { + OutputPage(p, all, formatter, cmd, type, page); + } + } + + static void OutputPage(Player p, List all, Func formatter, + string cmd, string type, int page) { + int total = all.Count, maxPage = total / perPage; + page = Utils.Clamp(page, 0, maxPage); + all.RemoveRange(0, page * perPage); + if (all.Count > perPage) + all.RemoveRange(perPage, all.Count - perPage); + + Player.Message(p, all.Join(formatter, ", ")); + int entriesEnd = Math.Min((page + 1) * perPage, total); + if (page < maxPage) { + Player.Message(p, "Showing {0} {1}-{2} (out of {3}) Next: %T/{4} {5}", + type, page * perPage + 1, entriesEnd, total, cmd, page + 1); + } else { + Player.Message(p, "Showing {0} {1}-{2} (out of {3})", + type, page * perPage + 1, entriesEnd, total); + } + + } + } +}