mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-08 14:48:47 -04:00
Perform partial name matching in /notes and /rankinfo
This commit is contained in:
parent
c5876ee307
commit
c1f13c4a5a
@ -126,15 +126,16 @@ namespace MCGalaxy.Gui {
|
||||
|
||||
|
||||
bool GetAutoload() {
|
||||
foreach (string line in Server.AutoloadMaps.Find(lvl.name + "="))
|
||||
return true;
|
||||
return false;
|
||||
return Server.AutoloadMaps.Find(lvl.name) != null;
|
||||
}
|
||||
|
||||
void SetAutoload(bool value) {
|
||||
Server.AutoloadMaps.DeleteStartsWith(lvl.name + "=");
|
||||
if (value)
|
||||
Server.AutoloadMaps.Append(lvl.name + "=" + lvl.physics);
|
||||
if (value) {
|
||||
Server.AutoloadMaps.AddOrReplace(lvl.name, lvl.physics.ToString());
|
||||
} else {
|
||||
Server.AutoloadMaps.Remove(lvl.name);
|
||||
}
|
||||
Server.AutoloadMaps.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +70,7 @@ namespace MCGalaxy.Commands {
|
||||
BlockDBChange.OutputMessageBlock(p, b, id, x, y, z);
|
||||
BlockDBChange.OutputPortal(p, b, id, x, y, z);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
|
||||
static void ListFromDatabase(Player p, ref bool foundAny, Dictionary<int, string> names,
|
||||
|
@ -16,6 +16,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace MCGalaxy.Commands {
|
||||
@ -28,19 +29,17 @@ namespace MCGalaxy.Commands {
|
||||
public CmdRankInfo() { }
|
||||
|
||||
public override void Use(Player p, string message) {
|
||||
if (message == "") {
|
||||
if (Player.IsSuper(p)) { SuperRequiresArgs(p, "player name"); return; }
|
||||
message = p.name;
|
||||
}
|
||||
Player who = PlayerInfo.Find(message);
|
||||
string target = who == null ? message : who.name;
|
||||
|
||||
Player.Message(p, " Rank information for {0}:",
|
||||
PlayerInfo.GetColoredName(p, target));
|
||||
bool found = false;
|
||||
if (CheckSuper(p, message, "player name")) return;
|
||||
if (message == "") message = p.name;
|
||||
|
||||
List<string> rankings = Server.RankInfo.FindMatches(p, message, "rankings");
|
||||
if (rankings == null) return;
|
||||
|
||||
string target = PlayerMetaList.GetName(rankings[0]);
|
||||
Player.Message(p, " Rankings for {0}:", PlayerInfo.GetColoredName(p, target));
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
foreach (string line in Server.RankInfo.Find(target)) {
|
||||
foreach (string line in rankings) {
|
||||
string[] parts = line.Split(' ');
|
||||
string newRank = Group.GetColoredName(parts[7]);
|
||||
string oldRank = Group.GetColoredName(parts[8]);
|
||||
@ -55,10 +54,7 @@ namespace MCGalaxy.Commands {
|
||||
Player.Message(p, "&aFrom {0} &ato {1} &a{2} ago",
|
||||
oldRank, newRank, delta.Shorten(true, false));
|
||||
Player.Message(p, "&aBy %S{0}&a, reason: %S{1}", parts[1], reason);
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
Player.Message(p, "&cPlayer has not been ranked yet.");
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
|
@ -28,8 +28,7 @@ namespace MCGalaxy.Commands {
|
||||
|
||||
public override void Use(Player p, string message) {
|
||||
Player.Message(p, "Forcing garbage collection...");
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
Player.Message(p, "Garbage collection completed!");
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MCGalaxy.Commands {
|
||||
public class CmdNotes : Command {
|
||||
@ -32,15 +33,13 @@ namespace MCGalaxy.Commands {
|
||||
if (CheckSuper(p, message, "player name")) return;
|
||||
if (message == "") message = p.name;
|
||||
|
||||
int matches = 1;
|
||||
Player who = message == "" ? p : PlayerInfo.FindMatches(p, message, out matches);
|
||||
if (matches > 1) return;
|
||||
if (who != null) message = who.name;
|
||||
List<string> notes = Server.Notes.FindMatches(p, message, "notes");
|
||||
if (notes == null) return;
|
||||
|
||||
Player.Message(p, "Notes for " + message + ":");
|
||||
bool foundAny = false;
|
||||
foreach (string line in Server.Notes.Find(message)) {
|
||||
foundAny = true;
|
||||
string target = PlayerMetaList.GetName(notes[0]);
|
||||
Player.Message(p, " Notes for {0}:", PlayerInfo.GetColoredName(p, target));
|
||||
|
||||
foreach (string line in notes) {
|
||||
string[] args = line.Split(' ');
|
||||
if (args.Length <= 3) continue;
|
||||
|
||||
@ -50,8 +49,6 @@ namespace MCGalaxy.Commands {
|
||||
Player.Message(p, Action(args[1]) + " by " + args[2] + " on " + args[3]
|
||||
+ " - " + args[4].Replace("%20", " "));
|
||||
}
|
||||
if (!foundAny)
|
||||
Player.Message(p, "No notes found.");
|
||||
}
|
||||
|
||||
static string Action(string arg) {
|
||||
|
@ -52,8 +52,7 @@ namespace MCGalaxy.Commands.World {
|
||||
lvl.Save(true);
|
||||
} finally {
|
||||
lvl.Dispose();
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Server.ErrorLog(ex);
|
||||
@ -61,7 +60,6 @@ namespace MCGalaxy.Commands.World {
|
||||
return;
|
||||
}
|
||||
Player.Message(p, "Converted map!");
|
||||
//CmdLoad.LoadLevel(p, name); pls
|
||||
}
|
||||
|
||||
enum FileType { Mcf, Fcm, Dat, Cw };
|
||||
|
@ -45,8 +45,7 @@ namespace MCGalaxy.Commands.World {
|
||||
try {
|
||||
return LoadLevelCore(p, name, phys, autoLoaded);
|
||||
} finally {
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,8 +79,7 @@ namespace MCGalaxy.Commands.World {
|
||||
Chat.MessageAll(format, pName, name, seed);
|
||||
} finally {
|
||||
if (p != null) Interlocked.Exchange(ref p.GeneratingMap, 0);
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -46,8 +46,7 @@ namespace MCGalaxy.Commands {
|
||||
}
|
||||
LevelActions.ReloadMap(p, who, true);
|
||||
}
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
|
||||
bool ReloadAll(Player p, string[] parts) {
|
||||
|
@ -85,8 +85,7 @@ namespace MCGalaxy.Commands.World {
|
||||
}
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
return Level.Load(lvl.name);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace MCGalaxy.Commands.World {
|
||||
|
||||
public override void Use(Player p, string message) {
|
||||
string name = message.ToLower();
|
||||
if (name == "" && Player.IsSuper(p)) { SuperRequiresArgs(p, "level name"); return; }
|
||||
if (CheckSuper(p, message, "level name")) return;
|
||||
|
||||
if (name == "") {
|
||||
if (!p.level.Unload()) {
|
||||
|
@ -158,8 +158,7 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
if (pl.level.name.CaselessEq(lvl.name))
|
||||
LevelActions.ReloadMap(p, pl, true);
|
||||
}
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,11 +56,6 @@ namespace fNbt {
|
||||
}
|
||||
byte[] bytes = ZeroArray;
|
||||
|
||||
public byte this[int tagIndex] {
|
||||
get { return Value[tagIndex]; }
|
||||
set { Value[tagIndex] = value; }
|
||||
}
|
||||
|
||||
internal override void ReadTag(NbtBinaryReader readStream) {
|
||||
int length = readStream.ReadInt32();
|
||||
if (length < 0)
|
||||
@ -233,16 +228,14 @@ namespace fNbt {
|
||||
|
||||
public byte ByteValue {
|
||||
get {
|
||||
if (TagType == NbtTagType.Byte)
|
||||
return ((NbtByte)this).Value;
|
||||
if (TagType == NbtTagType.Byte) return ((NbtByte)this).Value;
|
||||
throw new InvalidCastException("Cannot get ByteValue from " + TagType);
|
||||
}
|
||||
}
|
||||
|
||||
public float FloatValue {
|
||||
get {
|
||||
if (TagType == NbtTagType.Float)
|
||||
return ((NbtFloat)this).Value;
|
||||
if (TagType == NbtTagType.Float) return ((NbtFloat)this).Value;
|
||||
throw new InvalidCastException("Cannot get FloatValue from " + TagType);
|
||||
}
|
||||
}
|
||||
@ -250,10 +243,8 @@ namespace fNbt {
|
||||
public short ShortValue {
|
||||
get {
|
||||
switch (TagType) {
|
||||
case NbtTagType.Byte:
|
||||
return ((NbtByte)this).Value;
|
||||
case NbtTagType.Short:
|
||||
return ((NbtShort)this).Value;
|
||||
case NbtTagType.Byte: return ((NbtByte)this).Value;
|
||||
case NbtTagType.Short: return ((NbtShort)this).Value;
|
||||
default:
|
||||
throw new InvalidCastException("Cannot get ShortValue from " + TagType);
|
||||
}
|
||||
@ -263,12 +254,9 @@ namespace fNbt {
|
||||
public int IntValue {
|
||||
get {
|
||||
switch (TagType) {
|
||||
case NbtTagType.Byte:
|
||||
return ((NbtByte)this).Value;
|
||||
case NbtTagType.Short:
|
||||
return ((NbtShort)this).Value;
|
||||
case NbtTagType.Int:
|
||||
return ((NbtInt)this).Value;
|
||||
case NbtTagType.Byte: return ((NbtByte)this).Value;
|
||||
case NbtTagType.Short: return ((NbtShort)this).Value;
|
||||
case NbtTagType.Int: return ((NbtInt)this).Value;
|
||||
default:
|
||||
throw new InvalidCastException("Cannot get IntValue from " + TagType);
|
||||
}
|
||||
@ -277,16 +265,14 @@ namespace fNbt {
|
||||
|
||||
public byte[] ByteArrayValue {
|
||||
get {
|
||||
if (TagType == NbtTagType.ByteArray)
|
||||
return ((NbtByteArray)this).Value;
|
||||
if (TagType == NbtTagType.ByteArray) return ((NbtByteArray)this).Value;
|
||||
throw new InvalidCastException("Cannot get ByteArrayValue from " + TagType);
|
||||
}
|
||||
}
|
||||
|
||||
public string StringValue {
|
||||
get {
|
||||
if (TagType == NbtTagType.String)
|
||||
return ((NbtString)this).Value;
|
||||
if (TagType == NbtTagType.String) return ((NbtString)this).Value;
|
||||
throw new InvalidCastException("Cannot get StringValue from " + TagType);
|
||||
}
|
||||
}
|
||||
@ -331,25 +317,22 @@ namespace fNbt {
|
||||
public override short ReadInt16() {
|
||||
if (swapNeeded) {
|
||||
return Swap(base.ReadInt16());
|
||||
} else {
|
||||
return base.ReadInt16();
|
||||
}
|
||||
return base.ReadInt16();
|
||||
}
|
||||
|
||||
public override int ReadInt32() {
|
||||
if (swapNeeded) {
|
||||
return Swap(base.ReadInt32());
|
||||
} else {
|
||||
return base.ReadInt32();
|
||||
}
|
||||
return base.ReadInt32();
|
||||
}
|
||||
|
||||
public override long ReadInt64() {
|
||||
if (swapNeeded) {
|
||||
return Swap(base.ReadInt64());
|
||||
} else {
|
||||
return base.ReadInt64();
|
||||
}
|
||||
return base.ReadInt64();
|
||||
}
|
||||
|
||||
public override float ReadSingle() {
|
||||
@ -357,9 +340,8 @@ namespace fNbt {
|
||||
FillBuffer(sizeof(float));
|
||||
Array.Reverse(buffer, 0, sizeof(float));
|
||||
return BitConverter.ToSingle(buffer, 0);
|
||||
} else {
|
||||
return base.ReadSingle();
|
||||
}
|
||||
return base.ReadSingle();
|
||||
}
|
||||
|
||||
public override double ReadDouble() {
|
||||
@ -405,25 +387,19 @@ namespace fNbt {
|
||||
}
|
||||
|
||||
static short Swap(short v) {
|
||||
unchecked {
|
||||
return (short)((v >> 8) & 0x00FF | (v << 8) & 0xFF00);
|
||||
}
|
||||
return (short)((v >> 8) & 0x00FF | (v << 8) & 0xFF00);
|
||||
}
|
||||
|
||||
static int Swap(int v) {
|
||||
unchecked {
|
||||
uint v2 = (uint)v;
|
||||
return
|
||||
(int)
|
||||
((v2 >> 24) & 0x000000FF | (v2 >> 8) & 0x0000FF00 | (v2 << 8) & 0x00FF0000 |
|
||||
(v2 << 24) & 0xFF000000);
|
||||
}
|
||||
uint v2 = (uint)v;
|
||||
return
|
||||
(int)
|
||||
((v2 >> 24) & 0x000000FF | (v2 >> 8) & 0x0000FF00 | (v2 << 8) & 0x00FF0000 |
|
||||
(v2 << 24) & 0xFF000000);
|
||||
}
|
||||
|
||||
static long Swap(long v) {
|
||||
unchecked {
|
||||
return (Swap((int)v) & uint.MaxValue) << 32 | Swap((int)(v >> 32)) & uint.MaxValue;
|
||||
}
|
||||
return (Swap((int)v) & uint.MaxValue) << 32 | Swap((int)(v >> 32)) & uint.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,8 +204,7 @@ namespace MCGalaxy {
|
||||
} catch {
|
||||
} finally {
|
||||
Dispose();
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
|
||||
if (!silent) Chat.MessageOps(ColoredName + " %Swas unloaded.");
|
||||
Server.s.Log(name + " was unloaded.");
|
||||
@ -271,8 +270,7 @@ namespace MCGalaxy {
|
||||
Chat.MessageAll("FAILED TO SAVE {0}", ColoredName);
|
||||
Server.ErrorLog(e);
|
||||
}
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
|
||||
void SaveCore(string path) {
|
||||
|
@ -332,8 +332,7 @@ namespace MCGalaxy {
|
||||
SendMessage("There was an error sending the map data, you have been sent to the main level.");
|
||||
Server.ErrorLog(ex);
|
||||
} finally {
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
@ -23,49 +23,50 @@ using System.Text;
|
||||
namespace MCGalaxy {
|
||||
public sealed class PlayerExtList {
|
||||
|
||||
char separator = ' ';
|
||||
string path;
|
||||
List<string> players = new List<string>();
|
||||
List<string> names = new List<string>();
|
||||
public List<string> lines = new List<string>();
|
||||
readonly object locker = new object(), saveLocker = new object();
|
||||
|
||||
public void Add(string p, string data) {
|
||||
p = p.ToLower();
|
||||
public void Add(string name, string data) {
|
||||
name = name.ToLower();
|
||||
lock (locker) {
|
||||
players.Add(p); lines.Add(p + " " + data);
|
||||
names.Add(name); lines.Add(name + separator + data);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(string p) {
|
||||
public bool Remove(string name) {
|
||||
lock (locker) {
|
||||
int idx = players.IndexOf(p.ToLower());
|
||||
int idx = names.IndexOf(name.ToLower());
|
||||
if (idx == -1) return false;
|
||||
|
||||
players.RemoveAt(idx);
|
||||
names.RemoveAt(idx);
|
||||
lines.RemoveAt(idx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddOrReplace(string p, string data) {
|
||||
p = p.ToLower();
|
||||
public void AddOrReplace(string name, string data) {
|
||||
name = name.ToLower();
|
||||
lock (locker) {
|
||||
int idx = players.IndexOf(p);
|
||||
int idx = names.IndexOf(name);
|
||||
if (idx == -1) {
|
||||
players.Add(p); lines.Add(p + " " + data);
|
||||
names.Add(name); lines.Add(name + separator + data);
|
||||
} else {
|
||||
lines[idx] = p + " " + data;
|
||||
lines[idx] = name + separator + data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Find(string p) {
|
||||
public string Find(string name) {
|
||||
lock (locker) {
|
||||
int idx = players.IndexOf(p.ToLower());
|
||||
int idx = names.IndexOf(name.ToLower());
|
||||
return idx == -1 ? null : lines[idx];
|
||||
}
|
||||
}
|
||||
|
||||
public int Count { get { lock (locker) return players.Count; } }
|
||||
public int Count { get { lock (locker) return names.Count; } }
|
||||
|
||||
|
||||
public void Save() { Save(true); }
|
||||
@ -84,9 +85,10 @@ namespace MCGalaxy {
|
||||
}
|
||||
}
|
||||
|
||||
public static PlayerExtList Load(string path) {
|
||||
public static PlayerExtList Load(string path, char separator = ' ') {
|
||||
PlayerExtList list = new PlayerExtList();
|
||||
list.path = path;
|
||||
list.separator = separator;
|
||||
|
||||
if (!File.Exists(path)) {
|
||||
File.Create(path).Close();
|
||||
@ -98,8 +100,8 @@ namespace MCGalaxy {
|
||||
string line = null;
|
||||
while ((line = r.ReadLine()) != null) {
|
||||
list.lines.Add(line);
|
||||
int space = line.IndexOf(' ');
|
||||
string name = space >= 0 ? line.Substring(0, space) : line;
|
||||
int sepIndex = line.IndexOf(separator);
|
||||
string name = sepIndex >= 0 ? line.Substring(0, sepIndex) : line;
|
||||
|
||||
// Need to convert uppercase to lowercase, in case user added in entries.
|
||||
bool anyUpper = false;
|
||||
@ -108,7 +110,7 @@ namespace MCGalaxy {
|
||||
anyUpper |= (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
if (anyUpper) name = name.ToLower();
|
||||
list.players.Add(name);
|
||||
list.names.Add(name);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
@ -67,7 +67,7 @@ namespace MCGalaxy {
|
||||
public string FindMatches(Player p, string name, string type, out int matches) {
|
||||
lock (locker) {
|
||||
return Matcher.Find<string>(p, name, out matches, players,
|
||||
n => true, n => n, type, 20);
|
||||
null, n => n, type, 20);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,9 +33,18 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
public void EnsureExists() {
|
||||
if (!File.Exists(file))
|
||||
if (!File.Exists(file))
|
||||
File.Create(file).Dispose();
|
||||
}
|
||||
|
||||
/// <summary> Adds the given line to the end of the file. </summary>
|
||||
public void Append(string data) {
|
||||
lock (locker) {
|
||||
using (StreamWriter w = new StreamWriter(file, true))
|
||||
w.WriteLine(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Finds all lines which caselessly start with the given name. </summary>
|
||||
public IEnumerable<string> Find(string name) {
|
||||
@ -50,36 +59,28 @@ namespace MCGalaxy {
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
public List<string> FindMatches(Player p, string name, string group) {
|
||||
int matches = 0;
|
||||
return Matcher.FindMulti<string>(p, name, out matches, AllLines(),
|
||||
null, GetName, group);
|
||||
}
|
||||
|
||||
/// <summary> Deletes all lines which start with the given value. </summary>
|
||||
public void DeleteStartsWith(string value) {
|
||||
if (!File.Exists(file)) return;
|
||||
List<string> lines = new List<string>();
|
||||
IEnumerable<string> AllLines() {
|
||||
if (!File.Exists(file)) yield break;
|
||||
|
||||
using (StreamReader r = new StreamReader(file)) {
|
||||
string line;
|
||||
while ((line = r.ReadLine()) != null) {
|
||||
if (line.StartsWith(value)) continue;
|
||||
lines.Add(line);
|
||||
yield return line;
|
||||
}
|
||||
}
|
||||
WriteLines(lines);
|
||||
yield break;
|
||||
}
|
||||
|
||||
void WriteLines(List<string> lines) {
|
||||
lock (locker) {
|
||||
using (StreamWriter w = new StreamWriter(file, false)) {
|
||||
foreach (string line in lines)
|
||||
w.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Adds the given line to the end of the file. </summary>
|
||||
public void Append(string data) {
|
||||
lock (locker) {
|
||||
using (StreamWriter w = new StreamWriter(file, true))
|
||||
w.WriteLine(data);
|
||||
}
|
||||
public static string GetName(string line) {
|
||||
int index = line.IndexOf(' ');
|
||||
return index == -1 ? line : line.Substring(0, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,8 +59,7 @@ namespace MCGalaxy {
|
||||
GotoLevel(p, lvl, ignorePerms) : GotoMap(p, name, ignorePerms);
|
||||
} finally {
|
||||
Interlocked.Exchange(ref p.UsingGoto, 0);
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
Server.DoGC();
|
||||
}
|
||||
|
||||
if (!didJoin) return false;
|
||||
|
@ -52,7 +52,7 @@ namespace MCGalaxy {
|
||||
public static Thread locationChecker;
|
||||
public static DateTime StartTime, StartTimeLocal;
|
||||
|
||||
public static PlayerMetaList AutoloadMaps = new PlayerMetaList("text/autoload.txt");
|
||||
public static PlayerExtList AutoloadMaps;
|
||||
public static PlayerMetaList RankInfo = new PlayerMetaList("text/rankinfo.txt");
|
||||
public static PlayerMetaList TempRanks = new PlayerMetaList("text/tempranks.txt");
|
||||
public static PlayerMetaList Notes = new PlayerMetaList("text/notes.txt");
|
||||
|
@ -94,17 +94,17 @@ namespace MCGalaxy {
|
||||
whiteList = PlayerList.Load("whitelist.txt");
|
||||
}
|
||||
|
||||
void LoadAutoloadCommands() {
|
||||
if (File.Exists("text/autoload.txt")) {
|
||||
PropertiesFile.Read("text/autoload.txt", AutoLoadLineProcessor);
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
} else {
|
||||
Log("autoload.txt does not exist");
|
||||
void LoadAutoloadMaps() {
|
||||
AutoloadMaps = PlayerExtList.Load("text/autoload.txt", '=');
|
||||
foreach (string line in AutoloadMaps.lines) {
|
||||
int sepIndex = line.IndexOf('=');
|
||||
string name = sepIndex >= 0 ? line.Substring(0, sepIndex) : line;
|
||||
string value = sepIndex >= 0 ? line.Substring(sepIndex + 1) : "";
|
||||
AutoLoadMap(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void AutoLoadLineProcessor(string name, string phys) {
|
||||
static void AutoLoadMap(string name, string phys) {
|
||||
name = name.ToLower();
|
||||
if (phys == "") phys = "0";
|
||||
|
||||
|
@ -108,7 +108,7 @@ namespace MCGalaxy {
|
||||
Plugin.Load();
|
||||
Background.QueueOnce(UpgradeTasks.UpgradeOldBlacklist);
|
||||
Background.QueueOnce(LoadPlayerLists);
|
||||
Background.QueueOnce(LoadAutoloadCommands);
|
||||
Background.QueueOnce(LoadAutoloadMaps);
|
||||
Background.QueueOnce(UpgradeTasks.MovePreviousLevelFiles);
|
||||
Background.QueueOnce(UpgradeTasks.UpgradeOldLockdown);
|
||||
|
||||
@ -366,5 +366,15 @@ namespace MCGalaxy {
|
||||
level = mapName;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void DoGC() {
|
||||
long start = GC.GetTotalMemory(false);
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
|
||||
long end = GC.GetTotalMemory(false);
|
||||
double delta = (start - end) / 1024.0;
|
||||
Server.s.Log("GC performed (freed " + delta.ToString("F2") + " KB)", true);
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
@ -82,16 +83,8 @@ namespace MCGalaxy {
|
||||
|
||||
|
||||
/// <summary> Finds partial matches of 'name' against the names of the items in the 'items' enumerable. </summary>
|
||||
/// <param name="pl"> The player to output messages to. </param>
|
||||
/// <param name="name"> The name to perform partial matching against. </param>
|
||||
/// <param name="matches"> The number of found/outputted matches. </param>
|
||||
/// <param name="items"> Enumerable of items that may be matched with. </param>
|
||||
/// <param name="filter"> Selects which items from 'items' are actually matched. </param>
|
||||
/// <param name="nameGetter"> Gets the name of a particular item. </param>
|
||||
/// <param name="group"> The group/type of the items. (e.g. 'players', 'commands') </param>
|
||||
/// <param name="limit"> The maximum number of matches that are outputted. </param>
|
||||
/// <returns> If exactly one match, the matching item. </returns>
|
||||
public static T Find<T>(Player pl, string name, out int matches, IEnumerable items,
|
||||
public static T Find<T>(Player p, string name, out int matches, IEnumerable items,
|
||||
Predicate<T> filter, Func<T, string> nameGetter, string group, int limit = 5) {
|
||||
T match = default(T); matches = 0;
|
||||
StringBuilder nameMatches = new StringBuilder();
|
||||
@ -110,19 +103,76 @@ namespace MCGalaxy {
|
||||
}
|
||||
}
|
||||
|
||||
if (matches == 1) return match;
|
||||
if (matches == 0) {
|
||||
Player.Message(pl, "No " + group + " match \"" + name + "\".");
|
||||
return default(T);
|
||||
} else if (matches == 1) {
|
||||
return match;
|
||||
Player.Message(p, "No " + group + " match \"" + name + "\".");
|
||||
} else {
|
||||
string count = matches > limit ? limit + "+ " : matches + " ";
|
||||
string names = nameMatches.ToString(0, nameMatches.Length - 2);
|
||||
|
||||
Player.Message(pl, count + group + " match \"" + name + "\":");
|
||||
Player.Message(pl, names);
|
||||
return default(T);
|
||||
OutputMulti(p, name, nameMatches, matches, group, limit);
|
||||
}
|
||||
return default(T);
|
||||
}
|
||||
|
||||
/// <summary> Finds partial matches of 'name' against the names of the items in the 'items' enumerable. </summary>
|
||||
/// <remarks> Outputs multiple matching entries, as 'items' enumerable may have multiple entries. </remarks>
|
||||
/// <returns> If exactly one match, the matching list of items. </returns>
|
||||
public static List<T> FindMulti<T>(Player p, string name, out int matches, IEnumerable items,
|
||||
Predicate<T> filter, Func<T, string> nameGetter, string group, int limit = 5) {
|
||||
List<T> matchItems = null; matches = 0;
|
||||
StringBuilder nameMatches = new StringBuilder();
|
||||
List<string> outputtedNames = new List<string>(limit);
|
||||
string match = null;
|
||||
|
||||
foreach (T item in items) {
|
||||
if (filter != null && !filter(item)) continue;
|
||||
string itemName = nameGetter(item);
|
||||
|
||||
// Found an exact name match - only output items now which exactly match
|
||||
if (itemName.Equals(name, comp)) {
|
||||
if (match == null || !name.Equals(match, comp))
|
||||
matchItems = new List<T>();
|
||||
matchItems.Add(item);
|
||||
|
||||
matches = 1; match = name;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemName.IndexOf(name, comp) < 0) continue;
|
||||
if (matches == 0) { // Found our first partial match - init the list
|
||||
matchItems = new List<T>();
|
||||
matchItems.Add(item);
|
||||
match = itemName;
|
||||
} else if (match != null && itemName.Equals(match, comp)) { // Found same partial match
|
||||
matchItems.Add(item);
|
||||
}
|
||||
|
||||
// We do not want to output the same name multiple times
|
||||
if (outputtedNames.CaselessContains(itemName) || matches > (limit + 1)) continue;
|
||||
matches++;
|
||||
|
||||
if (matches <= limit) {
|
||||
nameMatches.Append(itemName).Append(", ");
|
||||
} else if (matches == limit + 1) {
|
||||
nameMatches.Append("(and more)").Append(", ");
|
||||
}
|
||||
outputtedNames.Add(itemName);
|
||||
}
|
||||
|
||||
if (matches == 1) return matchItems;
|
||||
if (matches == 0) {
|
||||
Player.Message(p, "No " + group + " found for \"" + name + "\".");
|
||||
} else {
|
||||
OutputMulti(p, name, nameMatches, matches, "players", limit);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static void OutputMulti(Player p, string name, StringBuilder nameMatches,
|
||||
int matches, string group, int limit = 5) {
|
||||
string count = matches > limit ? limit + "+ " : matches + " ";
|
||||
string names = nameMatches.ToString(0, nameMatches.Length - 2);
|
||||
|
||||
Player.Message(p, count + group + " match \"" + name + "\":");
|
||||
Player.Message(p, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user