mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-22 03:55:18 -04:00
Add /os list, sort lists of displayed levels a bit more nicely
This commit is contained in:
parent
aeda35c708
commit
5ce514187f
@ -16,7 +16,6 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace MCGalaxy.Commands.Info
|
||||
{
|
||||
@ -31,55 +30,11 @@ namespace MCGalaxy.Commands.Info
|
||||
}
|
||||
|
||||
public override void Use(Player p, string message, CommandData data) {
|
||||
string[] files = LevelInfo.AllMapFiles();
|
||||
string[] files = LevelInfo.AllMapNames();
|
||||
// Files list is not guaranteed to be in alphabetical order
|
||||
Array.Sort(files);
|
||||
|
||||
p.Message("Levels (&c[no] &Sif not visitable):");
|
||||
Paginator.Output(p, files, (file) => FormatMap(p, file),
|
||||
"Levels", "levels", message);
|
||||
Array.Sort(files, new AlphanumComparator());
|
||||
LevelInfo.ListMaps(p, files, "Levels", "Levels", "levels", message);
|
||||
}
|
||||
|
||||
static string FormatMap(Player p, string file) {
|
||||
LevelPermission visitP, buildP;
|
||||
bool loadOnGoto;
|
||||
string map = Path.GetFileNameWithoutExtension(file);
|
||||
RetrieveProps(map, out visitP, out buildP, out loadOnGoto);
|
||||
|
||||
LevelPermission maxPerm = visitP;
|
||||
if (maxPerm < buildP) maxPerm = buildP;
|
||||
|
||||
string visit = loadOnGoto && p.Rank >= visitP ? "" : " &c[no]";
|
||||
return Group.GetColor(maxPerm) + map + visit;
|
||||
}
|
||||
|
||||
static void RetrieveProps(string level, out LevelPermission visit,
|
||||
out LevelPermission build, out bool loadOnGoto) {
|
||||
visit = LevelPermission.Guest;
|
||||
build = LevelPermission.Guest;
|
||||
loadOnGoto = true;
|
||||
|
||||
string propsPath = LevelInfo.PropsPath(level);
|
||||
SearchArgs args = new SearchArgs();
|
||||
if (!PropertiesFile.Read(propsPath, ref args, ProcessLine)) return;
|
||||
|
||||
visit = Group.ParsePermOrName(args.Visit, visit);
|
||||
build = Group.ParsePermOrName(args.Build, build);
|
||||
if (!bool.TryParse(args.LoadOnGoto, out loadOnGoto))
|
||||
loadOnGoto = true;
|
||||
}
|
||||
|
||||
static void ProcessLine(string key, string value, ref SearchArgs args) {
|
||||
if (key.CaselessEq("pervisit")) {
|
||||
args.Visit = value;
|
||||
} else if (key.CaselessEq("perbuild")) {
|
||||
args.Build = value;
|
||||
} else if (key.CaselessEq("loadongoto")) {
|
||||
args.LoadOnGoto = value;
|
||||
}
|
||||
}
|
||||
|
||||
struct SearchArgs { public string Visit, Build, LoadOnGoto; }
|
||||
|
||||
public override void Help(Player p) {
|
||||
p.Message("&T/Levels");
|
||||
|
@ -108,6 +108,7 @@ namespace MCGalaxy.Commands.Info
|
||||
static void SearchMaps(Player p, string keyword, string modifier) {
|
||||
string[] allMaps = LevelInfo.AllMapNames();
|
||||
List<string> maps = Wildcard.Filter(allMaps, keyword, map => map);
|
||||
maps.Sort(new AlphanumComparator());
|
||||
OutputList(p, keyword, "search levels", "maps", modifier, maps);
|
||||
}
|
||||
|
||||
|
@ -56,11 +56,8 @@ namespace MCGalaxy.Commands.World {
|
||||
string[] allMaps = LevelInfo.AllMapNames();
|
||||
|
||||
int realmsOwned = 0;
|
||||
foreach (string lvlName in allMaps)
|
||||
{
|
||||
if (!lvlName.CaselessStarts(p.name)) continue;
|
||||
|
||||
if (LevelInfo.IsRealmOwner(p.name, lvlName)) {
|
||||
foreach (string lvlName in allMaps) {
|
||||
if (IsOwnedBy(p.name, lvlName)) {
|
||||
realmsOwned += 1;
|
||||
if (realmsOwned >= p.group.OverseerMaps) {
|
||||
break;
|
||||
@ -81,6 +78,22 @@ namespace MCGalaxy.Commands.World {
|
||||
p.Message("You have reached the limit for your overseer maps.");
|
||||
return null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns all the os maps owned by p, sorted alphabetically.
|
||||
/// </summary>
|
||||
static List<string> AllOwnedBy(string playerName) {
|
||||
string[] allMaps = LevelInfo.AllMapNames();
|
||||
List<string> owned = new List<string>();
|
||||
foreach (string lvlName in allMaps) {
|
||||
if (IsOwnedBy(playerName, lvlName)) owned.Add(lvlName);
|
||||
}
|
||||
owned.Sort(new AlphanumComparator());
|
||||
return owned;
|
||||
}
|
||||
|
||||
static bool IsOwnedBy(string playerName, string levelName) {
|
||||
return levelName.CaselessStarts(playerName) && LevelInfo.IsRealmOwner(playerName, levelName);
|
||||
}
|
||||
|
||||
static string[] addHelp = new string[] {
|
||||
"&T/os add &H- Creates a flat map (128x128x128).",
|
||||
@ -479,6 +492,22 @@ namespace MCGalaxy.Commands.World {
|
||||
static void HandleRestore(Player p, string args) {
|
||||
UseCommand(p, "Restore", args);
|
||||
}
|
||||
|
||||
static string[] listHelp = new string[] {
|
||||
"&T/os list <player>",
|
||||
"&H Lists all the os realms for <player>",
|
||||
"&H By default, lists your own realms.",
|
||||
};
|
||||
static void HandleList(Player p, string args) {
|
||||
string[] words = args.SplitSpaces(2);
|
||||
string word0 = words[0];
|
||||
string word1 = words.Length > 1 ? words[1] : ""; //How many times have I typed a variant of this
|
||||
|
||||
string playerName = word0.Length == 0 ? p.name : PlayerInfo.FindMatchesPreferOnline(p, word0);
|
||||
if (playerName == null) return;
|
||||
string page = word1;
|
||||
LevelInfo.ListMaps(p, AllOwnedBy(playerName), "OS realms", "os list "+playerName, "OS realms", page, playerName != p.name);
|
||||
}
|
||||
|
||||
//Placed at the end so that the help arrays aren't null
|
||||
internal static SubCommandGroup subCommandGroup = new SubCommandGroup(commandShortcut,
|
||||
@ -510,6 +539,7 @@ namespace MCGalaxy.Commands.World {
|
||||
new SubCommand("Delete", HandleDelete, deleteHelp, true, new string[] { "del", "remove" } ),
|
||||
new SubCommand("Rename", HandleRename, renameHelp),
|
||||
new SubCommand("Restore", HandleRestore, restoreHelp),
|
||||
new SubCommand("List", HandleList, listHelp, false),
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using MCGalaxy.DB;
|
||||
@ -240,5 +241,56 @@ namespace MCGalaxy {
|
||||
// Match the backwards compatibilty case of IsRealmOwner
|
||||
return PlayerDB.FindName(map);
|
||||
}
|
||||
|
||||
public static void ListMaps(Player p, IList<string> maps, string levelsTitle, string listCmd, string itemName, string page, bool showVisitable = true) {
|
||||
p.Message("{0} (&c[no] &Sif not visitable):", levelsTitle);
|
||||
Paginator.Output(p, maps, (file) => FormatMap(p, file, showVisitable),
|
||||
listCmd, itemName, page);
|
||||
}
|
||||
static string FormatMap(Player p, string map, bool showVisitable) {
|
||||
LevelPermission visitP, buildP;
|
||||
bool loadOnGoto;
|
||||
RetrieveProps(map, out visitP, out buildP, out loadOnGoto);
|
||||
|
||||
LevelPermission maxPerm = visitP;
|
||||
if (maxPerm < buildP) maxPerm = buildP;
|
||||
|
||||
string visit;
|
||||
if (showVisitable) {
|
||||
visit = loadOnGoto && p.Rank >= visitP ? "" : " &c[no]";
|
||||
} else {
|
||||
visit = "";
|
||||
}
|
||||
return Group.GetColor(maxPerm) + map + visit;
|
||||
}
|
||||
|
||||
static void RetrieveProps(string level, out LevelPermission visit,
|
||||
out LevelPermission build, out bool loadOnGoto) {
|
||||
visit = LevelPermission.Guest;
|
||||
build = LevelPermission.Guest;
|
||||
loadOnGoto = true;
|
||||
|
||||
string propsPath = LevelInfo.PropsPath(level);
|
||||
SearchArgs args = new SearchArgs();
|
||||
if (!PropertiesFile.Read(propsPath, ref args, ProcessLine)) return;
|
||||
|
||||
visit = Group.ParsePermOrName(args.Visit, visit);
|
||||
build = Group.ParsePermOrName(args.Build, build);
|
||||
if (!bool.TryParse(args.LoadOnGoto, out loadOnGoto))
|
||||
loadOnGoto = true;
|
||||
}
|
||||
|
||||
static void ProcessLine(string key, string value, ref SearchArgs args) {
|
||||
if (key.CaselessEq("pervisit")) {
|
||||
args.Visit = value;
|
||||
} else if (key.CaselessEq("perbuild")) {
|
||||
args.Build = value;
|
||||
} else if (key.CaselessEq("loadongoto")) {
|
||||
args.LoadOnGoto = value;
|
||||
}
|
||||
}
|
||||
|
||||
struct SearchArgs { public string Visit, Build, LoadOnGoto; }
|
||||
|
||||
}
|
||||
}
|
@ -130,4 +130,46 @@ namespace MCGalaxy
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts a list of strings such that a1 a2 a3 comes before a10 a11 a12 and so on.
|
||||
/// </summary>
|
||||
public class AlphanumComparator : IComparer<string> {
|
||||
|
||||
// Simplified but based off of https://www.dotnetperls.com/alphanumeric-sorting
|
||||
public int Compare(string a, string b) {
|
||||
int result;
|
||||
int aLen, bLen;
|
||||
int aDigit = GetDigits(a, out aLen);
|
||||
int bDigit = GetDigits(b, out bLen);
|
||||
if (aDigit != -1 && bDigit != -1) {
|
||||
result = aDigit.CompareTo(bDigit);
|
||||
} else {
|
||||
result = a.Substring(0, aLen).CompareTo(b.Substring(0, bLen));
|
||||
}
|
||||
if (result != 0) return result;
|
||||
return a.Length - b.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the digits on the end of the string. -1 if no integer found.
|
||||
/// </summary>
|
||||
static int GetDigits(string name, out int nameLength) {
|
||||
nameLength = name.Length;
|
||||
if (!Char.IsDigit(name[name.Length - 1])) return -1;
|
||||
|
||||
int decimalShift = 1;
|
||||
int number = 0;
|
||||
for (int i = name.Length - 1; i >= 0; i--) {
|
||||
if (!Char.IsDigit(name[i])) return number;
|
||||
|
||||
nameLength--;
|
||||
int digit = name[i] - '0'; //Paige Ruten: here's the most insane way to convert a digit char to an integer
|
||||
number += digit * decimalShift;
|
||||
decimalShift *= 10;
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user