Add a multi page command output (thanks fCraft for layout idea).

This commit is contained in:
UnknownShadow200 2016-09-06 15:25:07 +10:00
parent e18d4df815
commit 683179d162
4 changed files with 91 additions and 51 deletions

View File

@ -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<string> 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;
}

View File

@ -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");

View File

@ -610,6 +610,7 @@
<Compile Include="util\Formatter.cs" />
<Compile Include="util\Math\DirUtils.cs" />
<Compile Include="util\Math\Vectors.cs" />
<Compile Include="util\MultiPageOutput.cs" />
<Compile Include="util\SparseBitSet.cs" />
<Compile Include="util\TimeUtils.cs" />
<Compile Include="util\Utils.cs" />

67
util/MultiPageOutput.cs Normal file
View File

@ -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 {
/// <summary> Outputs a large range of values across a number of 'pages'. </summary>
public static class MultiPageOutput {
const int perPage = 30;
public static void Output<T>(Player p, IEnumerable<T> items, Func<T, string> formatter,
string cmd, string type, string input) {
List<T> all = new List<T>(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<T>(Player p, List<T> all, Func<T, string> 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);
}
}
}
}