From fca6ae43b38027224eb32f11272341f664435028 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 25 Jan 2017 12:08:56 +1100 Subject: [PATCH] fix /copylvl and /renamelvl with blockprops (thanks nosliw) --- .../Blocks/Physics/SimpleLiquidPhysics.cs | 2 +- MCGalaxy/Bots/PlayerBot.cs | 4 +- MCGalaxy/CmdMapsBy.cs | 83 +++++++++++++++++ MCGalaxy/Commands/Information/CmdAfk.cs | 15 ++-- MCGalaxy/Commands/other/CmdBack.cs | 2 +- MCGalaxy/Economy/Awards.cs | 4 +- MCGalaxy/Levels/LevelActions.cs | 89 +++++++++++-------- MCGalaxy/Levels/LevelInfo.cs | 8 +- MCGalaxy/MCGalaxy_.csproj | 7 +- MCGalaxy/Player/Group/Group.cs | 4 +- MCGalaxy/Player/List/PlayerList.cs | 4 +- MCGalaxy/Player/PlayerInfo.cs | 10 +-- MCGalaxy/util/{ => Formatting}/Formatter.cs | 0 MCGalaxy/util/Formatting/Matcher.cs | 67 ++++++++++++++ .../util/{ => Formatting}/MultiPageOutput.cs | 0 15 files changed, 233 insertions(+), 66 deletions(-) create mode 100644 MCGalaxy/CmdMapsBy.cs rename MCGalaxy/util/{ => Formatting}/Formatter.cs (100%) create mode 100644 MCGalaxy/util/Formatting/Matcher.cs rename MCGalaxy/util/{ => Formatting}/MultiPageOutput.cs (100%) diff --git a/MCGalaxy/Blocks/Physics/SimpleLiquidPhysics.cs b/MCGalaxy/Blocks/Physics/SimpleLiquidPhysics.cs index 0f9e9f761..3bbc31978 100644 --- a/MCGalaxy/Blocks/Physics/SimpleLiquidPhysics.cs +++ b/MCGalaxy/Blocks/Physics/SimpleLiquidPhysics.cs @@ -56,7 +56,7 @@ namespace MCGalaxy.Blocks.Physics { public static void DoFastLava(Level lvl, ref Check C) { if (lvl.randomFlow) { DoLavaRandowFlow(lvl, ref C, false); - if (C.data.Data != 255) + if (C.data.Data != PhysicsArgs.RemoveFromChecks) C.data.Data = 0; // no lava delay } else { DoLavaUniformFlow(lvl, ref C, false); diff --git a/MCGalaxy/Bots/PlayerBot.cs b/MCGalaxy/Bots/PlayerBot.cs index c920614b8..b97251bc9 100644 --- a/MCGalaxy/Bots/PlayerBot.cs +++ b/MCGalaxy/Bots/PlayerBot.cs @@ -143,8 +143,8 @@ namespace MCGalaxy { public static PlayerBot FindMatches(Player pl, string name) { int matches = 0; - return Utils.FindMatches(pl, name, out matches, Bots.Items, - b => true, b => b.name, "bots"); + return Matcher.Find(pl, name, out matches, Bots.Items, + b => true, b => b.name, "bots"); } public static PlayerBot FindMatchesPreferLevel(Player pl, string name) { diff --git a/MCGalaxy/CmdMapsBy.cs b/MCGalaxy/CmdMapsBy.cs new file mode 100644 index 000000000..107828be4 --- /dev/null +++ b/MCGalaxy/CmdMapsBy.cs @@ -0,0 +1,83 @@ +/* + Copyright 2011 MCForge + + 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; +using System.IO; +using System.Text; + +namespace MCGalaxy.Commands { + + public sealed class CmdMapsBy : Command { + public override string name { get { return "mapsby"; } } + public override string shortcut { get { return "madeby"; } } + public override string type { get { return CommandTypes.Information; } } + public override bool museumUsable { get { return true; } } + public override LevelPermission defaultRank { get { return LevelPermission.Guest; } } + + public override void Use(Player p, string message) { + if (message == "") { Help(p); return; } + string author = PlayerInfo.FindOfflineNameMatches(p, message); + if (author == null) return; + + string[] maps = Directory.GetFiles("levels", "*.lvl"); + for (int i = 0; i < maps.Length; i++) { + maps[i] = Path.GetFileNameWithoutExtension(maps[i]); + } + + List madeBy = new List(); + foreach (string map in maps) { + if (!IsOwnedBy(map, author)) continue; + madeBy.Add(map); + } + + author = PlayerInfo.GetColoredName(p, author); + if (madeBy.Count == 0) { + Player.Message(p, "{0} %Shas not made any maps", author); + } else { + Player.Message(p, "{0} %Sauthored these maps: {1}", author, madeBy.Join()); + } + } + + static bool IsOwnedBy(string map, string name) { + if (map.CaselessStarts(name)) return true; + string file = LevelInfo.FindPropertiesFile(map); + if (file == null) return false; + + string realmOwner = null; + PropertiesFile.Read(file, ref realmOwner, ProcessLine); + if (realmOwner == null) return false; + + string[] owners = realmOwner.Replace(" ", "").Split(','); + foreach (string owner in owners) { + if (owner.CaselessEq(name)) return true; + } + return false; + } + + static void ProcessLine(string key, string value, ref string realmOwner) { + if (key.CaselessEq("realmowner")) { + realmOwner = value; + } + } + + public override void Help(Player p) { + Player.Message(p, "%T/mapsby %H[player]"); + Player.Message(p, "%HLists all maps authored by the given player."); + } + } +} diff --git a/MCGalaxy/Commands/Information/CmdAfk.cs b/MCGalaxy/Commands/Information/CmdAfk.cs index f7058b623..fa4d6875a 100644 --- a/MCGalaxy/Commands/Information/CmdAfk.cs +++ b/MCGalaxy/Commands/Information/CmdAfk.cs @@ -47,11 +47,9 @@ namespace MCGalaxy.Commands { bool cantSend = p.muted || (Server.chatmod && !p.voice); if (p.IsAfk) { if (cantSend) { - Player.Message(p, "You are now marked as being AFK."); + Player.Message(p, "You are now marked as being AFK."); } else { - Chat.MessageWhere("-{0}%S- is AFK {1}", - pl => Entities.CanSee(pl, p) && !pl.listignored.Contains(p.name) && !pl.ignoreAll, - p.ColoredName, message); + MessageOthers(p, "-" + p.ColoredName + "%S- is AFK " + message); Player.RaisePlayerAction(p, PlayerAction.AFK, message); p.CheckForMessageSpam(); } @@ -64,15 +62,18 @@ namespace MCGalaxy.Commands { if (cantSend) { Player.Message(p, "You are no longer marked as being AFK."); } else { - Chat.MessageWhere("-{0}%S- is no longer AFK", - pl => Entities.CanSee(pl, p) && !pl.listignored.Contains(p.name) && !pl.ignoreAll, - p.ColoredName); + MessageOthers(p, "-" + p.ColoredName + "%S- is no longer AFK"); Player.RaisePlayerAction(p, PlayerAction.UnAFK, message); p.CheckForMessageSpam(); } } } + static void MessageOthers(Player p, string msg) { + Chat.MessageWhere(msg, + pl => Entities.CanSee(pl, p) && !pl.listignored.Contains(p.name) && !pl.ignoreAll); + } + public override void Help(Player p) { Player.Message(p, "%T/afk "); Player.Message(p, "%HMarks yourself as AFK. Use again to mark yourself as back"); diff --git a/MCGalaxy/Commands/other/CmdBack.cs b/MCGalaxy/Commands/other/CmdBack.cs index a313b5968..05bd48365 100644 --- a/MCGalaxy/Commands/other/CmdBack.cs +++ b/MCGalaxy/Commands/other/CmdBack.cs @@ -31,7 +31,7 @@ namespace MCGalaxy.Commands { p.SendMessage("You have not teleported anywhere yet"); return; } - if (p.level.name.ToLower() != p.beforeTeleportMap.ToLower()) + if (!p.level.name.CaselessEq(p.beforeTeleportMap)) PlayerActions.ChangeMap(p, p.beforeTeleportMap); p.SendPos(Entities.SelfID, p.beforeTeleportPos[0], p.beforeTeleportPos[1], p.beforeTeleportPos[2], 0, 0); } diff --git a/MCGalaxy/Economy/Awards.cs b/MCGalaxy/Economy/Awards.cs index de7b87c0b..394495d27 100644 --- a/MCGalaxy/Economy/Awards.cs +++ b/MCGalaxy/Economy/Awards.cs @@ -196,8 +196,8 @@ namespace MCGalaxy { } public static string FindMatches(Player p, string name, out int matches) { - Award award = Utils.FindMatches(p, name, out matches, AwardsList, - a => true, a => a.Name, "awards"); + Award award = Matcher.Find(p, name, out matches, AwardsList, + a => true, a => a.Name, "awards"); return award == null ? null : award.Name; } diff --git a/MCGalaxy/Levels/LevelActions.cs b/MCGalaxy/Levels/LevelActions.cs index c62219cd9..361806337 100644 --- a/MCGalaxy/Levels/LevelActions.cs +++ b/MCGalaxy/Levels/LevelActions.cs @@ -30,31 +30,18 @@ namespace MCGalaxy { /// Does not perform any unloading. public static void Rename(string src, string dst) { File.Move(LevelInfo.LevelPath(src), LevelInfo.LevelPath(dst)); - try { - File.Move(LevelInfo.LevelPath(src) + ".backup", LevelInfo.LevelPath(dst) + ".backup"); - } catch { - } - try { - File.Move("levels/level properties/" + src + ".properties", - "levels/level properties/" + dst + ".properties"); - } catch { - } + SafeMove(LevelInfo.LevelPath(src) + ".backup", + LevelInfo.LevelPath(dst) + ".backup"); + SafeMove("levels/level properties/" + src, + "levels/level properties/" + dst + ".properties"); + SafeMove("levels/level properties/" + src + ".properties", + "levels/level properties/" + dst + ".properties"); + SafeMove("blockdefs/lvl_" + src + ".json", + "blockdefs/lvl_" + dst + ".json"); + SafeMove("blockprops/lvl_" + src + ".txt", + "blockprops/lvl_" + dst + ".txt"); - try { - File.Move("levels/level properties/" + src, - "levels/level properties/" + dst + ".properties"); - } catch { - } - - try { - if (File.Exists("blockdefs/lvl_" + src + ".json")) { - File.Move("blockdefs/lvl_" + src + ".json", - "blockdefs/lvl_" + dst + ".json"); - } - } catch { - } - try { MoveBackups(src, dst); } catch { @@ -88,6 +75,15 @@ namespace MCGalaxy { } } + static void SafeMove(string src, string dst) { + if (!File.Exists(src)) return; + try { + File.Move(src, dst); + } catch (Exception ex) { + Server.ErrorLog(ex); + } + } + static bool DirectoryEmpty(string dir) { if (!Directory.Exists(dir)) return true; if (Directory.GetDirectories(dir).Length > 0) return false; @@ -131,13 +127,11 @@ namespace MCGalaxy { File.Move(LevelInfo.LevelPath(name), "levels/deleted/" + name + ".lvl"); } - try { File.Delete("levels/level properties/" + name + ".properties"); } catch { } - try { File.Delete("levels/level properties/" + name); } catch { } - try { - if (File.Exists("blockdefs/lvl_" + name + ".json")) - File.Delete("blockdefs/lvl_" + name + ".json"); - } catch {} - + SafeDelete("levels/level properties/" + name); + SafeDelete("levels/level properties/" + name + ".properties"); + SafeDelete("blockdefs/lvl_" + name + ".json"); + SafeDelete("blockprops/lvl_" + name + ".txt"); + BotsFile.DeleteBots(name); DeleteDatabaseTables(name); BlockDBFile.DeleteBackingFile(name); @@ -160,6 +154,16 @@ namespace MCGalaxy { } } } + + static void SafeDelete(string src) { + if (!File.Exists(src)) return; + try { + File.Delete(src); + } catch (Exception ex) { + Server.ErrorLog(ex); + } + } + public static void Replace(Level old, Level lvl) { LevelDB.SaveBlockDB(old); @@ -198,15 +202,15 @@ namespace MCGalaxy { public static void CopyLevel(string src, string dst) { File.Copy(LevelInfo.LevelPath(src), LevelInfo.LevelPath(dst)); - if (File.Exists(LevelInfo.PropertiesPath(src))) { - File.Copy(LevelInfo.PropertiesPath(src), - LevelInfo.PropertiesPath(dst)); - } - if (File.Exists("blockdefs/lvl_" + src + ".json")) { - File.Copy("blockdefs/lvl_" + src + ".json", - "blockdefs/lvl_" + dst + ".json"); - } + SafeCopy("levels/level properties/" + src, + "levels/level properties/" + dst + ".properties"); + SafeCopy("levels/level properties/" + src + ".properties", + "levels/level properties/" + dst + ".properties"); + SafeCopy("blockdefs/lvl_" + src + ".json", + "blockdefs/lvl_" + dst + ".json"); + SafeCopy("blockprops/lvl_" + src + ".txt", + "blockprops/lvl_" + dst + ".txt"); CopyDatabaseTables(src, dst); } @@ -234,5 +238,14 @@ namespace MCGalaxy { } } } + + static void SafeCopy(string src, string dst) { + if (!File.Exists(src)) return; + try { + File.Copy(src, dst, true); + } catch (Exception ex) { + Server.ErrorLog(ex); + } + } } } diff --git a/MCGalaxy/Levels/LevelInfo.cs b/MCGalaxy/Levels/LevelInfo.cs index 16b1c9cc1..6a5b868de 100644 --- a/MCGalaxy/Levels/LevelInfo.cs +++ b/MCGalaxy/Levels/LevelInfo.cs @@ -45,8 +45,8 @@ namespace MCGalaxy { } public static Level FindMatches(Player pl, string name, out int matches) { - return Utils.FindMatches(pl, name, out matches, LevelInfo.Loaded.Items, - l => true, l => l.name, "loaded levels"); + return Matcher.Find(pl, name, out matches, LevelInfo.Loaded.Items, + l => true, l => l.name, "loaded levels"); } public static string FindMapMatches(Player pl, string name) { @@ -60,8 +60,8 @@ namespace MCGalaxy { } string[] files = Directory.GetFiles("levels", "*.lvl"); - string map = Utils.FindMatches(pl, name, out matches, files, - l => true, l => Path.GetFileNameWithoutExtension(l), "levels"); + string map = Matcher.Find(pl, name, out matches, files, + l => true, l => Path.GetFileNameWithoutExtension(l), "levels"); if (map != null) map = Path.GetFileNameWithoutExtension(map); return map; diff --git a/MCGalaxy/MCGalaxy_.csproj b/MCGalaxy/MCGalaxy_.csproj index c67953a37..a62457cb2 100644 --- a/MCGalaxy/MCGalaxy_.csproj +++ b/MCGalaxy/MCGalaxy_.csproj @@ -115,6 +115,7 @@ + @@ -620,12 +621,13 @@ - + + + - @@ -700,6 +702,7 @@ + diff --git a/MCGalaxy/Player/Group/Group.cs b/MCGalaxy/Player/Group/Group.cs index 64f56ceba..8f815e3dd 100644 --- a/MCGalaxy/Player/Group/Group.cs +++ b/MCGalaxy/Player/Group/Group.cs @@ -187,8 +187,8 @@ namespace MCGalaxy { public static Group FindMatches(Player p, string name, out int matches) { name = name.ToLower(); MapName(ref name); - return Utils.FindMatches(p, name, out matches, - GroupList, g => true, g => g.name, "ranks"); + return Matcher.Find(p, name, out matches, + GroupList, g => true, g => g.name, "ranks"); } /// Find the group(s) which contain the given name. diff --git a/MCGalaxy/Player/List/PlayerList.cs b/MCGalaxy/Player/List/PlayerList.cs index 92b879002..60ef47729 100644 --- a/MCGalaxy/Player/List/PlayerList.cs +++ b/MCGalaxy/Player/List/PlayerList.cs @@ -66,8 +66,8 @@ namespace MCGalaxy { public string FindMatches(Player p, string name, string type, out int matches) { lock (locker) { - return Utils.FindMatches(p, name, out matches, players, - n => true, n => n, type, 20); + return Matcher.Find(p, name, out matches, players, + n => true, n => n, type, 20); } } diff --git a/MCGalaxy/Player/PlayerInfo.cs b/MCGalaxy/Player/PlayerInfo.cs index b6bd06293..89457197d 100644 --- a/MCGalaxy/Player/PlayerInfo.cs +++ b/MCGalaxy/Player/PlayerInfo.cs @@ -63,9 +63,9 @@ namespace MCGalaxy { Player.Message(pl, "\"{0}\" is not a valid player name.", name); return null; } - return Utils.FindMatches(pl, name, out matches, Online.Items, - p => Entities.CanSee(pl, p) || !onlyCanSee, - p => p.name, "online players"); + return Matcher.Find(pl, name, out matches, Online.Items, + p => Entities.CanSee(pl, p) || !onlyCanSee, + p => p.name, "online players"); } public static string FindMatchesPreferOnline(Player p, string name) { @@ -191,8 +191,8 @@ namespace MCGalaxy { "WHERE Name LIKE @0 LIMIT 21" + suffix, "%" + name + "%")) { int matches = 0; - return Utils.FindMatches(p, name, out matches, results.Rows, - r => true, r => r["Name"].ToString(), "players", 20); + return Matcher.Find(p, name, out matches, results.Rows, + r => true, r => r["Name"].ToString(), "players", 20); } } } diff --git a/MCGalaxy/util/Formatter.cs b/MCGalaxy/util/Formatting/Formatter.cs similarity index 100% rename from MCGalaxy/util/Formatter.cs rename to MCGalaxy/util/Formatting/Formatter.cs diff --git a/MCGalaxy/util/Formatting/Matcher.cs b/MCGalaxy/util/Formatting/Matcher.cs new file mode 100644 index 000000000..97f5ada8d --- /dev/null +++ b/MCGalaxy/util/Formatting/Matcher.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; +using System.Text; + +namespace MCGalaxy { + public static class Matcher { + + const StringComparison comp = StringComparison.OrdinalIgnoreCase; + + /// Finds partial matches of 'name' against the names of the items in the 'items' enumerable. + /// The player to output messages to. + /// The name to perform partial matching against. + /// The number of found/outputted matches. + /// Enumerable of items that may be matched with. + /// Selects which items from 'items' are actually matched. + /// Gets the name of a particular item. + /// The type of the items. (e.g. 'players', 'commands') + /// The maximum number of matches that are outputted. + /// If exactly one match, the matching item. + public static T Find(Player pl, string name, out int matches, IEnumerable items, + Predicate filter, Func nameGetter, string type, int limit = 5) { + T match = default(T); matches = 0; + StringBuilder nameMatches = new StringBuilder(); + + foreach (T item in items) { + if (!filter(item)) continue; + string itemName = nameGetter(item); + if (itemName.Equals(name, comp)) { matches = 1; return item; } + if (itemName.IndexOf(name, comp) < 0) continue; + + match = item; matches++; + if (matches <= limit) + nameMatches.Append(itemName).Append(", "); + else if (matches == limit + 1) + nameMatches.Append("(and more)").Append(", "); + } + + if (matches == 0) { + Player.Message(pl, "No " + type + " match \"" + name + "\"."); return default(T); + } else if (matches == 1) { + return match; + } else { + string count = matches > limit ? limit + "+ " : matches + " "; + string names = nameMatches.ToString(0, nameMatches.Length - 2); + Player.Message(pl, count + type + " match \"" + name + "\":"); + Player.Message(pl, names); return default(T); + } + } + } +} diff --git a/MCGalaxy/util/MultiPageOutput.cs b/MCGalaxy/util/Formatting/MultiPageOutput.cs similarity index 100% rename from MCGalaxy/util/MultiPageOutput.cs rename to MCGalaxy/util/Formatting/MultiPageOutput.cs