From a204527ebbefc1eaf6b40ff90872d98ab1969e40 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 2 Sep 2016 14:56:27 +1000 Subject: [PATCH 01/16] Start rewriting economy database table structure - store money in Players table instead, with economy table only tracking players who have performed transactions. --- Economy/Economy.cs | 31 +++++++++++++++---------------- Player/Player.cs | 6 ------ Player/PlayerData.cs | 9 +-------- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/Economy/Economy.cs b/Economy/Economy.cs index 9b745c51d..13bbf6e94 100644 --- a/Economy/Economy.cs +++ b/Economy/Economy.cs @@ -55,21 +55,15 @@ PRIMARY KEY(player) } public static void LoadDatabase() { - retry: - Database.Execute(createTable); //create database - DataTable eco = Database.Fill("SELECT * FROM Economy"); - try { - DataTable players = Database.Fill("SELECT * FROM Players"); - if (players.Rows.Count == eco.Rows.Count) { } //move along, nothing to do here - else if (eco.Rows.Count == 0) { //if first time, copy content from player to economy - Database.Execute("INSERT INTO Economy (player, money) SELECT Players.Name, Players.Money FROM Players"); - } else { - //this will only be needed when the server shuts down while it was copying content (or some other error) - Database.Backend.DeleteTable("Economy"); - goto retry; - } - players.Dispose(); eco.Dispose(); - } catch { } + Database.Execute(createTable); + DataTable eco = Database.Fill("SELECT (player, money) FROM Economy"); + foreach (DataRow row in eco) { + int money = PlayerData.ParseInt(row["money"].ToString()); + if (money == 0) continue; + + UpdateMoney(row["player"].ToString(), money); + // TODO: remove zero money in Economy table + } } public static void Load() { @@ -109,7 +103,7 @@ PRIMARY KEY(player) public static void Save() { using (StreamWriter w = new StreamWriter("properties/economy.properties", false)) { - w.WriteLine("enabled:" + Enabled); + w.WriteLine("enabled:" + Enabled); foreach (Item item in Items) { w.WriteLine(); item.Serialise(w); @@ -143,6 +137,11 @@ PRIMARY KEY(player) Database.Execute(type + " Economy (player, money, total, purchase, payment, salary, fine) " + "VALUES (@0, @1, @2, @3, @4, @5, @6)", es.playerName, es.money, es.totalSpent, es.purchase, es.payment, es.salary, es.fine); + UpdateMoney(es.playerName, es.money); + } + + public static void UpdateMoney(string name, int money) { + Database.Execute("UPDATE Players SET Money=@0 WHERE Name=@1", name, money); } public static Item[] Items = { new ColorItem(), new TitleColorItem(), diff --git a/Player/Player.cs b/Player/Player.cs index 457da54ee..cfd6f879f 100644 --- a/Player/Player.cs +++ b/Player/Player.cs @@ -118,12 +118,6 @@ namespace MCGalaxy { totalLogins, overallDeath, money, blocks, cuboided, totalKicked, time.ToDBTime(), name); - if (Economy.Enabled && loginMoney != money) { - Economy.EcoStats ecos = Economy.RetrieveEcoStats(name); - ecos.money = money; - Economy.UpdateEcoStats(ecos); - } - Server.zombie.SaveZombieStats(this); SaveUndo(this); } diff --git a/Player/PlayerData.cs b/Player/PlayerData.cs index 272b8b794..6b894e024 100644 --- a/Player/PlayerData.cs +++ b/Player/PlayerData.cs @@ -46,11 +46,6 @@ namespace MCGalaxy { ", Money, totalBlocks, totalKicked, TimeSpent) VALUES (@0, @1, @2, @2, @3, @4, @5, @5, @5, @5, @6)"; Database.Execute(query, p.name, p.ip, now, 1, "", 0, p.time.ToDBTime()); - - const string ecoQuery = "INSERT INTO Economy (player, money, total, purchase, payment, salary, fine) " + - "VALUES (@0, @1, @2, @3, @3, @3, @3)"; - Database.Execute(ecoQuery, - p.name, p.money, 0, "%cNone"); } internal static void Load(DataTable playerDb, Player p) { @@ -74,9 +69,7 @@ namespace MCGalaxy { p.TotalPlaced = data.TotalPlaced; p.TotalDeleted = data.TotalDeleted; - //money = int.Parse(data.money); - p.money = Economy.RetrieveEcoStats(p.name).money; - p.loginMoney = p.money; + p.money = data.Money; p.totalKicked = data.Kicks; } From 96db138a35e9fb2d9dbb1702776961a2713d2a4e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 2 Sep 2016 20:26:33 +1000 Subject: [PATCH 02/16] Finish the Economy database rewrite. --- Commands/Economy/CmdBalance.cs | 50 ++++++++------- Commands/Economy/CmdFakePay.cs | 32 +++------- Commands/Economy/CmdGive.cs | 61 +++++++----------- Commands/Economy/CmdPay.cs | 72 +++++++++------------ Commands/Economy/CmdTake.cs | 74 +++++++++------------- Commands/Economy/MoneyCmd.cs | 58 +++++++++++++++++ Economy/Economy.cs | 112 ++++++++++++++++++--------------- MCGalaxy_.csproj | 1 + Player/PlayerInfo.cs | 4 +- 9 files changed, 246 insertions(+), 218 deletions(-) create mode 100644 Commands/Economy/MoneyCmd.cs diff --git a/Commands/Economy/CmdBalance.cs b/Commands/Economy/CmdBalance.cs index b07f9cdbe..937d79213 100644 --- a/Commands/Economy/CmdBalance.cs +++ b/Commands/Economy/CmdBalance.cs @@ -29,40 +29,42 @@ namespace MCGalaxy.Commands { public override CommandEnable Enabled { get { return CommandEnable.Economy; } } public override void Use(Player p, string message) { - Economy.EcoStats ecos; if (CheckSuper(p, message, "player name")) return; - + if (!ValidName(p, message, "player")) return; int matches = 1; Player who = message == "" ? p : PlayerInfo.FindMatches(p, message, out matches); if (matches > 1) return; - if (matches == 0) { - string dbName = PlayerInfo.FindOfflineNameMatches(p, message); - if (dbName == null) return; - - ecos = Economy.RetrieveEcoStats(dbName); - Player.Message(p, "%3===Economy stats for: %f" + ecos.playerName + "%7(offline)%3==="); - } else { - ecos = Economy.RetrieveEcoStats(who.name); - Player.Message(p, "%3===Economy stats for: " + who.color + who.name + "%3==="); - } - Player.Message(p, "Current balance: %f" + ecos.money + " %3" + Server.moneys); - Player.Message(p, "Total spent: %f" + ecos.totalSpent + " %3" + Server.moneys); - if (!(String.IsNullOrEmpty(ecos.purchase) || ecos.purchase == "%cNone")) - Player.Message(p, "Last purchase: " + ecos.purchase); - if (!(String.IsNullOrEmpty(ecos.payment) || ecos.payment == "%cNone")) - Player.Message(p, "Last payment: " + ecos.payment); - if (!(String.IsNullOrEmpty(ecos.salary) || ecos.salary == "%cNone")) - Player.Message(p, "Last receipt: " + ecos.salary); - if (!(String.IsNullOrEmpty(ecos.fine) || ecos.fine == "%cNone")) - Player.Message(p, "Last fine: " + ecos.fine); + string target = null; + int money = 0; + if (matches == 0) { + target = Economy.FindMatches(p, message, out money); + if (target == null) return; + } else { + target = who.name; money = who.money; + } + + string targetName = PlayerInfo.GetColoredName(p, target); + Chat.MessageAll("Economy stats for {0}%S:", targetName); + Player.Message(p, " Current balance: &f{0} &3{1}", money, Server.moneys); + + Economy.EcoStats ecos = Economy.RetrieveStats(target); + Player.Message(p, " Total spent: &f" + ecos.TotalSpent + " &3" + Server.moneys); + if (!(String.IsNullOrEmpty(ecos.Purchase) || ecos.Purchase == "%cNone")) + Player.Message(p, " Last purchase: " + ecos.Purchase); + if (!(String.IsNullOrEmpty(ecos.Payment) || ecos.Payment == "%cNone")) + Player.Message(p, " Last payment: " + ecos.Payment); + if (!(String.IsNullOrEmpty(ecos.Salary) || ecos.Salary == "%cNone")) + Player.Message(p, " Last receipt: " + ecos.Salary); + if (!(String.IsNullOrEmpty(ecos.Fine) || ecos.Fine == "%cNone")) + Player.Message(p, " Last fine: " + ecos.Fine); } public override void Help(Player p) { - Player.Message(p, "%T/balance "); + Player.Message(p, "%T/balance [player]"); Player.Message(p, "%HShows how much %3" + Server.moneys + " %H has, " + "plus their most recent transactions."); - Player.Message(p, "%HIf is not given, shows your own balance."); + Player.Message(p, "%HIf [player] is not given, shows your own balance."); } } } diff --git a/Commands/Economy/CmdFakePay.cs b/Commands/Economy/CmdFakePay.cs index 2d041863d..3dc1b3221 100644 --- a/Commands/Economy/CmdFakePay.cs +++ b/Commands/Economy/CmdFakePay.cs @@ -15,36 +15,24 @@ or implied. See the Licenses for the specific language governing permissions and limitations under the Licenses. */ -namespace MCGalaxy.Commands { - - public sealed class CmdFakePay : Command { - +namespace MCGalaxy.Commands { + public sealed class CmdFakePay : MoneyCmd { public override string name { get { return "fakepay"; } } public override string shortcut { get { return "fpay"; } } - public override string type { get { return CommandTypes.Economy; } } - public override bool museumUsable { get { return true; } } - public override LevelPermission defaultRank { get { return LevelPermission.Operator; } } - public override CommandEnable Enabled { get { return CommandEnable.Economy; } } + public override LevelPermission defaultRank { get { return LevelPermission.Operator; } } public override void Use(Player p, string message) { - if (message == "") { Help(p); return; } - - string[] args = message.Split(' '); - Player who = PlayerInfo.FindMatches(p, args[0]); - if (who == null) return; - - int amount = 0; - if (args.Length == 1 || !int.TryParse(args[1], out amount)) { - Player.Message(p, "You must specify an integer amount to fakepay."); return; - } - if (amount < 0) { Player.Message(p, "You can't fakepay a negative amount."); return; } - if (amount >= 16777215) { Player.Message(p, "You can only fakepay up to 16777215."); return; } + MoneyCmdData data; + if (!ParseArgs(p, message, false, "fakepay", out data)) return; + Player who = PlayerInfo.FindMatches(p, data.Name); + if (who == null) return; + if (data.Amount >= 16777215) { Player.Message(p, "You can only fakepay up to 16777215."); return; } - Chat.MessageAll("{0} %Swas given {1} {2}", who.ColoredName, amount, Server.moneys); + Chat.MessageAll("{0} %Swas given {1} {2}", who.ColoredName, data.Amount, Server.moneys); } public override void Help(Player p) { - Player.Message(p, "%T/fakepay "); + Player.Message(p, "%T/fakepay [name] [amount]"); Player.Message(p, "%HSends a fake give change message."); } } diff --git a/Commands/Economy/CmdGive.cs b/Commands/Economy/CmdGive.cs index 9dccc6f87..cc9934bce 100644 --- a/Commands/Economy/CmdGive.cs +++ b/Commands/Economy/CmdGive.cs @@ -17,58 +17,45 @@ */ using System; using System.Globalization; -namespace MCGalaxy.Commands -{ - public sealed class CmdGive : Command - { +namespace MCGalaxy.Commands { + public sealed class CmdGive : MoneyCmd { public override string name { get { return "give"; } } public override string shortcut { get { return "gib"; } } - public override string type { get { return CommandTypes.Economy; } } - public override bool museumUsable { get { return true; } } - public override LevelPermission defaultRank { get { return LevelPermission.Admin; } } - public override CommandEnable Enabled { get { return CommandEnable.Economy; } } + public override LevelPermission defaultRank { get { return LevelPermission.Admin; } } public CmdGive() { } public override void Use(Player p, string message) { - string[] args = message.Split(' '); - if (args.Length != 2) { Help(p); return; } - string giver = null, giverRaw = null; - if (p == null) { giverRaw = "(console)"; giver = "(console)"; } - else { giverRaw = p.color + p.name; giver = p.ColoredName; } - - int amount; - if (!int.TryParse(args[1], out amount)) { - Player.Message(p, "Amount must be an integer."); return; - } - if (amount < 0) { Player.Message(p, "Cannot give negative %3" + Server.moneys); return; } + MoneyCmdData data; + if (!ParseArgs(p, message, false, "give", out data)) return; int matches = 1; - Player who = PlayerInfo.FindMatches(p, args[0], out matches); + Player who = PlayerInfo.FindMatches(p, data.Name, out matches); if (matches > 1) return; if (p != null && p == who) { Player.Message(p, "You cannot give yourself %3" + Server.moneys); return; } - Economy.EcoStats ecos; + string target = null; + int money = 0; if (who == null) { - string dbName = PlayerInfo.FindOfflineNameMatches(p, args[0]); - if (dbName == null) return; + target = Economy.FindMatches(p, data.Name, out money); + if (target == null) return; - ecos = Economy.RetrieveEcoStats(dbName); - if (ReachedMax(p, ecos.money, amount)) return; - Chat.MessageAll("{0} %Sgave &f{1}%S(offline) &f{2} &3{3}", - giver, ecos.playerName, amount, Server.moneys); + if (ReachedMax(p, money, data.Amount)) return; + money += data.Amount; + Economy.UpdateMoney(target, money); } else { - if (ReachedMax(p, who.money, amount)) return; - ecos.money = who.money; - who.SetMoney(who.money + amount); - ecos = Economy.RetrieveEcoStats(who.name); - Chat.MessageAll("{0} %Sgave {1} &f{2} &3{3}", - giver, who.ColoredName, amount, Server.moneys); + target = who.name; money = who.money; + if (ReachedMax(p, money, data.Amount)) return; + who.SetMoney(who.money + data.Amount); } + + string targetName = PlayerInfo.GetColoredName(p, target); + Chat.MessageAll("{0} %Sgave {1} &f{2} &3{3}", + data.Source, targetName, data.Amount, Server.moneys); - ecos.money += amount; - ecos.salary = "%f" + amount + "%3 " + Server.moneys + " by " + - giverRaw + "%3 on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); - Economy.UpdateEcoStats(ecos); + Economy.EcoStats stats = Economy.RetrieveStats(target); + stats.Salary = "%f" + data.Amount + "%3 " + Server.moneys + " by " + + data.SourceRaw + "%3 on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); + Economy.UpdateStats(stats); } static bool ReachedMax(Player p, int current, int amount) { diff --git a/Commands/Economy/CmdPay.cs b/Commands/Economy/CmdPay.cs index 6cf6243f3..0605753dd 100644 --- a/Commands/Economy/CmdPay.cs +++ b/Commands/Economy/CmdPay.cs @@ -17,62 +17,52 @@ */ using System; using System.Globalization; -namespace MCGalaxy.Commands -{ - public sealed class CmdPay : Command - { + +namespace MCGalaxy.Commands { + public sealed class CmdPay : MoneyCmd { public override string name { get { return "pay"; } } public override string shortcut { get { return ""; } } - public override string type { get { return CommandTypes.Economy; } } - public override bool museumUsable { get { return true; } } - public override LevelPermission defaultRank { get { return LevelPermission.Banned; } } - public override CommandEnable Enabled { get { return CommandEnable.Economy; } } + public override LevelPermission defaultRank { get { return LevelPermission.Banned; } } public CmdPay() { } public override void Use(Player p, string message) { - string[] args = message.Split(' '); - if (args.Length != 2) { Help(p); return; } - int amount; - if (!int.TryParse(args[1], out amount)) { Player.Message(p, "Amount must be an integer."); return; } - if (amount < 0) { Player.Message(p, "Cannot pay negative %3" + Server.moneys); return; } + MoneyCmdData data; + if (!ParseArgs(p, message, false, "pay", out data)) return; int matches = 1; - Player who = PlayerInfo.FindMatches(p, args[0], out matches); + Player who = PlayerInfo.FindMatches(p, data.Name, out matches); if (matches > 1) return; if (p != null && p == who) { Player.Message(p, "You cannot pay yourself %3" + Server.moneys); return; } string target = null; - Economy.EcoStats payer, receiver; + int money; if (who == null) { - string dbName = PlayerInfo.FindOfflineNameMatches(p, args[0]); - if (dbName == null) return; + target = Economy.FindMatches(p, data.Name, out money); + if (target == null) return; - payer = Economy.RetrieveEcoStats(p.name); - receiver = Economy.RetrieveEcoStats(dbName); - if (!IsLegalPayment(p, payer.money, receiver.money, amount)) return; - - target = receiver.playerName; - Chat.MessageAll("{0} %Spaid &f{1}%S(offline) &f{2} &3{3}", - p.ColoredName, receiver.playerName, amount, Server.moneys); + if (!IsLegalPayment(p, p.money, money, data.Amount)) return; + money += data.Amount; + Economy.UpdateMoney(target, money); } else { - payer = Economy.RetrieveEcoStats(p.name); - receiver = Economy.RetrieveEcoStats(who.name); - if (!IsLegalPayment(p, payer.money, receiver.money, amount)) return; - - receiver.money = who.money; - who.SetMoney(who.money + amount); - target = who.color + who.name; - Chat.MessageAll("{0} %Spaid {1} &f{2} &3{3}", - p.ColoredName, who.ColoredName, amount, Server.moneys); + target = who.name; money = who.money; + if (!IsLegalPayment(p, p.money, money, data.Amount)) return; + who.SetMoney(who.money + data.Amount); } + + p.SetMoney(p.money - data.Amount); + string targetName = PlayerInfo.GetColoredName(p, target); + Chat.MessageAll("{0} %Spaid {1} &f{2} &3{3}", + data.Source, targetName, data.Amount, Server.moneys); - payer.payment = "%f" + amount + " %3" + Server.moneys + " to " + target + "%3 on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); - receiver.salary = "%f" + amount + " %3" + Server.moneys + " by " + p.color + p.name + "%3 on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); - receiver.money += amount; - p.SetMoney(p.money - amount); - payer.money = p.money; - Economy.UpdateEcoStats(payer); - Economy.UpdateEcoStats(receiver); + Economy.EcoStats stats = Economy.RetrieveStats(p.name); + stats.Payment = "%f" + data.Amount + " %3" + Server.moneys + " to " + + target + "%3 on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); + Economy.UpdateStats(stats); + + stats = Economy.RetrieveStats(target); + stats.Salary = "%f" + data.Amount + " %3" + Server.moneys + " by " + + p.color + p.name + "%3 on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); + Economy.UpdateStats(stats); } bool IsLegalPayment(Player p, int payer, int receiver, int amount) { @@ -83,7 +73,7 @@ namespace MCGalaxy.Commands public override void Help(Player p) { Player.Message(p, "%T/pay [player] [amount] "); - Player.Message(p, "%HPays %3" + Server.moneys + " %Hto [player]"); + Player.Message(p, "%HPays [amount] &3" + Server.moneys + " %Hto [player]"); } } } diff --git a/Commands/Economy/CmdTake.cs b/Commands/Economy/CmdTake.cs index fddcab615..4ebe8e56e 100644 --- a/Commands/Economy/CmdTake.cs +++ b/Commands/Economy/CmdTake.cs @@ -19,70 +19,58 @@ using System; using System.Globalization; namespace MCGalaxy.Commands { - public sealed class CmdTake : Command { + public sealed class CmdTake : MoneyCmd { public override string name { get { return "take"; } } public override string shortcut { get { return ""; } } - public override string type { get { return CommandTypes.Economy; } } - public override bool museumUsable { get { return true; } } - public override LevelPermission defaultRank { get { return LevelPermission.Admin; } } - public override CommandEnable Enabled { get { return CommandEnable.Economy; } } + public override LevelPermission defaultRank { get { return LevelPermission.Admin; } } public CmdTake() { } public override void Use(Player p, string message) { - string[] args = message.Split(' '); - if (args.Length != 2) { Help(p); return; } - - string taker = null, takerRaw = null; - if (p == null) { takerRaw = "(console)"; taker = "(console)"; } - else { takerRaw = p.color + p.name; taker = p.ColoredName; } - - int amount = 0; - bool all = args[1].CaselessEq("all"); - if (!all && !int.TryParse(args[1], out amount)) { - Player.Message(p, "Amount must be an integer."); return; - } - if (amount < 0) { Player.Message(p, "%cYou can't take negative %3" + Server.moneys); return; } + MoneyCmdData data; + if (!ParseArgs(p, message, true, "take", out data)) return; int matches = 1; - Player who = PlayerInfo.FindMatches(p, args[0], out matches); + Player who = PlayerInfo.FindMatches(p, data.Name, out matches); if (matches > 1) return; if (p != null && p == who) { Player.Message(p, "%cYou can't take %3" + Server.moneys + "%c from yourself"); return; } - Economy.EcoStats ecos; + string target = null; + int money = 0; if (who == null) { - string dbName = PlayerInfo.FindOfflineNameMatches(p, args[0]); - if (dbName == null) return; - - ecos = Economy.RetrieveEcoStats(dbName); - Take(all, ref ecos, ref amount); - Chat.MessageAll("{0} %Stook &f{2} &3{3} %Sfrom &f{1}%S(offline)", - p.ColoredName, ecos.playerName, amount, Server.moneys); + target = Economy.FindMatches(p, data.Name, out money); + if (target == null) return; + Take(ref money, ref data); + Economy.UpdateMoney(target, money); } else { - ecos = Economy.RetrieveEcoStats(who.name); - ecos.money = who.money; - Take(all, ref ecos, ref amount); - who.SetMoney(ecos.money); - Chat.MessageAll("{0} %Stook &f{2} &3{3} %Sfrom {1}", - p.ColoredName, who.ColoredName, amount, Server.moneys); + target = who.name; money = who.money; + Take(ref money, ref data); + who.SetMoney(money); } - ecos.fine = "%f" + amount + " %3" + Server.moneys + " by " + takerRaw + "%3 on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); - Economy.UpdateEcoStats(ecos); + + string targetName = PlayerInfo.GetColoredName(p, target); + Chat.MessageAll("{0} %Stook &f{2} &3{3} %Sfrom {1}", + data.Source, targetName, data.Amount, Server.moneys); + + Economy.EcoStats stats = Economy.RetrieveStats(target); + stats.Fine = "%f" + data.Amount + "%3 " + Server.moneys + " by " + + data.SourceRaw + "%3 on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); + Economy.UpdateStats(stats); } - static void Take(bool all, ref Economy.EcoStats ecos, ref int amount) { - if (all || ecos.money < amount) { - amount = ecos.money; - ecos.money = 0; + static void Take(ref int money, ref MoneyCmdData data) { + if (data.All || money < data.Amount) { + data.Amount = money; + money = 0; } else { - ecos.money -= amount; + money -= data.Amount; } } public override void Help(Player p){ - Player.Message(p, "%T/take [player] "); - Player.Message(p, "%HTakes of " + Server.moneys + " from [player]"); + Player.Message(p, "%T/take [player] [amount["); + Player.Message(p, "%HTakes [amount] of &3" + Server.moneys + " %Sfrom [player]"); Player.Message(p, "%T/take [player] all"); - Player.Message(p, "%HTakes all the " + Server.moneys + " from [player]"); + Player.Message(p, "%HTakes all the &3" + Server.moneys + " %Sfrom [player]"); } } } diff --git a/Commands/Economy/MoneyCmd.cs b/Commands/Economy/MoneyCmd.cs new file mode 100644 index 000000000..09163d7da --- /dev/null +++ b/Commands/Economy/MoneyCmd.cs @@ -0,0 +1,58 @@ +/* + 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.Globalization; + +namespace MCGalaxy.Commands { + public abstract class MoneyCmd : Command { + public override string type { get { return CommandTypes.Economy; } } + public override bool museumUsable { get { return true; } } + public override CommandEnable Enabled { get { return CommandEnable.Economy; } } + + protected bool ParseArgs(Player p, string message, bool canAll, + string action, out MoneyCmdData data) { + data = default(MoneyCmdData); + string[] args = message.Split(' '); + if (args.Length != 2) { Help(p); return false; } + data.Name = args[0]; + + if (p == null) { + data.SourceRaw = "(console)"; data.Source = "(console)"; + } else { + data.SourceRaw = p.color + p.name; data.Source = p.ColoredName; + } + + int amount = 0; + data.All = canAll && args[1].CaselessEq("all"); + if (!data.All && !int.TryParse(args[1], out amount)) { + Player.Message(p, "Amount to {0} must be an integer.", action); return false; + } + if (amount < 0) { + Player.Message(p, "You cannot {0} negative &3" + Server.moneys, action); return false; + } + data.Amount = amount; + return true; + } + + protected struct MoneyCmdData { + public string Source, SourceRaw, Name; + public int Amount; + public bool All; + } + } +} diff --git a/Economy/Economy.cs b/Economy/Economy.cs index 13bbf6e94..45e554285 100644 --- a/Economy/Economy.cs +++ b/Economy/Economy.cs @@ -41,28 +41,37 @@ PRIMARY KEY(player) );"; public struct EcoStats { - public string playerName, purchase, payment, salary, fine; - public int money, totalSpent; - public EcoStats(string name, int mon, int tot, string pur, string pay, string sal, string fin) { - playerName = name; - money = mon; - totalSpent = tot; - purchase = pur; - payment = pay; - salary = sal; - fine = fin; + public string Player, Purchase, Payment, Salary, Fine; + public int TotalSpent; + + public EcoStats(int tot, string player, string pur, + string pay, string sal, string fin) { + TotalSpent = tot; + Player = player; + Purchase = pur; + Payment = pay; + Salary = sal; + Fine = fin; } } public static void LoadDatabase() { Database.Execute(createTable); - DataTable eco = Database.Fill("SELECT (player, money) FROM Economy"); - foreach (DataRow row in eco) { + DataTable eco = Database.Fill("SELECT * FROM Economy"); + foreach (DataRow row in eco.Rows) { int money = PlayerData.ParseInt(row["money"].ToString()); if (money == 0) continue; - UpdateMoney(row["player"].ToString(), money); - // TODO: remove zero money in Economy table + EcoStats stats; + stats.Player = row["player"].ToString(); + stats.Payment = row["payment"].ToString(); + stats.Purchase = row["purchase"].ToString(); + stats.Salary = row["salary"].ToString(); + stats.Fine = row["fine"].ToString(); + stats.TotalSpent = PlayerData.ParseInt(row["total"].ToString()); + + UpdateMoney(stats.Player, money); + UpdateStats(stats); } } @@ -110,38 +119,43 @@ PRIMARY KEY(player) } } } - - public static EcoStats RetrieveEcoStats(string playername) { - EcoStats es = default(EcoStats); - es.playerName = playername; - using (DataTable eco = Database.Fill("SELECT * FROM Economy WHERE player=@0", playername)) { - if (eco.Rows.Count >= 1) { - es.money = int.Parse(eco.Rows[0]["money"].ToString()); - es.totalSpent = int.Parse(eco.Rows[0]["total"].ToString()); - es.purchase = eco.Rows[0]["purchase"].ToString(); - es.payment = eco.Rows[0]["payment"].ToString(); - es.salary = eco.Rows[0]["salary"].ToString(); - es.fine = eco.Rows[0]["fine"].ToString(); - } else { - es.purchase = "%cNone"; - es.payment = "%cNone"; - es.salary = "%cNone"; - es.fine = "%cNone"; - } - } - return es; - } - - public static void UpdateEcoStats(EcoStats es) { + + public static void UpdateStats(EcoStats stats) { string type = Server.useMySQL ? "REPLACE INTO" : "INSERT OR REPLACE INTO"; Database.Execute(type + " Economy (player, money, total, purchase, payment, salary, fine) " + - "VALUES (@0, @1, @2, @3, @4, @5, @6)", es.playerName, es.money, es.totalSpent, - es.purchase, es.payment, es.salary, es.fine); - UpdateMoney(es.playerName, es.money); + "VALUES (@0, @1, @2, @3, @4, @5, @6)", stats.Player, 0, stats.TotalSpent, + stats.Purchase, stats.Payment, stats.Salary, stats.Fine); + } + + public static EcoStats RetrieveStats(string name) { + EcoStats stats = default(EcoStats); + stats.Player = name; + + using (DataTable eco = Database.Fill("SELECT * FROM Economy WHERE player=@0", name)) { + if (eco.Rows.Count > 0) { + stats.TotalSpent = int.Parse(eco.Rows[0]["total"].ToString()); + stats.Purchase = eco.Rows[0]["purchase"].ToString(); + stats.Payment = eco.Rows[0]["payment"].ToString(); + stats.Salary = eco.Rows[0]["salary"].ToString(); + stats.Fine = eco.Rows[0]["fine"].ToString(); + } else { + stats.Purchase = "%cNone"; + stats.Payment = "%cNone"; + stats.Salary = "%cNone"; + stats.Fine = "%cNone"; + } + } + return stats; + } + + public static string FindMatches(Player p, string name, out int money) { + DataRow row = PlayerInfo.QueryMulti(p, name, "Name, Money"); + money = row == null ? 0 : PlayerData.ParseInt(row["Money"].ToString()); + return row == null ? null : row["Name"].ToString(); } public static void UpdateMoney(string name, int money) { - Database.Execute("UPDATE Players SET Money=@0 WHERE Name=@1", name, money); + Database.Execute("UPDATE Players SET Money=@0 WHERE Name=@1", money, name); } public static Item[] Items = { new ColorItem(), new TitleColorItem(), @@ -172,15 +186,15 @@ PRIMARY KEY(player) public static RankItem Ranks { get { return (RankItem)Items[3]; } } public static LevelItem Levels { get { return (LevelItem)Items[4]; } } - public static void MakePurchase(Player p, int cost, string item) { - Economy.EcoStats ecos = RetrieveEcoStats(p.name); + public static void MakePurchase(Player p, int cost, string item) { p.SetMoney(p.money - cost); - ecos.money = p.money; - ecos.totalSpent += cost; - ecos.purchase = item + "%3 - Price: %f" + cost + " %3" + Server.moneys + - " - Date: %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); - UpdateEcoStats(ecos); - Player.Message(p, "%aYour balance is now %f" + p.money + " %3" + Server.moneys); + Player.Message(p, "Your balance is now &f{0} &3{1}", p.money, Server.moneys); + + Economy.EcoStats stats = RetrieveStats(p.name); + stats.TotalSpent += cost; + stats.Purchase = item + "%3 for %f" + cost + " %3" + Server.moneys + + " on %f" + DateTime.Now.ToString(CultureInfo.InvariantCulture); + Economy.UpdateStats(stats); } } } \ No newline at end of file diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index 5a2c4ee99..295e800b4 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -216,6 +216,7 @@ + diff --git a/Player/PlayerInfo.cs b/Player/PlayerInfo.cs index 0bf6fb3b9..9c081a6f2 100644 --- a/Player/PlayerInfo.cs +++ b/Player/PlayerInfo.cs @@ -180,14 +180,14 @@ namespace MCGalaxy { } - static DataTable Query(string name, string selector) { + internal static DataTable Query(string name, string selector) { string syntax = Server.useMySQL ? "SELECT " + selector + " FROM Players WHERE Name=@0 COLLATE utf8_general_ci" : "SELECT " + selector + " FROM Players WHERE Name=@0 COLLATE NOCASE"; return Database.Fill(syntax, name); } - static DataRow QueryMulti(Player p, string name, string selector) { + internal static DataRow QueryMulti(Player p, string name, string selector) { string syntax = Server.useMySQL ? "SELECT " + selector + " FROM Players WHERE Name LIKE @0 LIMIT 21" : "SELECT " + selector + " FROM Players WHERE Name LIKE @0 LIMIT 21 COLLATE NOCASE"; From 9c2ba4d4fb1ae2f3b8c946a0751a097059cea6e1 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 2 Sep 2016 20:50:44 +1000 Subject: [PATCH 03/16] Fix disconnect player showing 'joined the game' on IRC. --- Network/IRCBot.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Network/IRCBot.cs b/Network/IRCBot.cs index b24d58b71..27a6b37f7 100644 --- a/Network/IRCBot.cs +++ b/Network/IRCBot.cs @@ -177,7 +177,7 @@ namespace MCGalaxy { void Player_PlayerDisconnect(Player p, string reason) { if (!Server.irc ||!IsConnected() || p.hidden) return; if (!Server.guestLeaveNotify && p.Rank <= LevelPermission.Guest) return; - Say(p.DisplayName + " %Sjoined the game (" + reason + "%S)", false); + Say(p.DisplayName + " %Sleft the game (" + reason + "%S)", false); } void Player_PlayerConnect(Player p) { From 3c9b503048115159b6f06e58fc36805f56ba2b50 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 3 Sep 2016 08:17:58 +1000 Subject: [PATCH 04/16] Fix voicing someone giving them the wrong color in /who. (Thanks lordmaker) --- Commands/Information/CmdPlayers.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Commands/Information/CmdPlayers.cs b/Commands/Information/CmdPlayers.cs index 7104b5976..918e9a30a 100644 --- a/Commands/Information/CmdPlayers.cs +++ b/Commands/Information/CmdPlayers.cs @@ -113,10 +113,12 @@ namespace MCGalaxy.Commands public void Append(Player pl, string name) { builder.Append(' '); - if (pl.voice) builder.Append("&f+%S"); + if (pl.voice) { + builder.Append("&f+").Append(group.color); + } builder.Append(name); - builder.Append(" (" + pl.level.name + "),"); + builder.Append(" (").Append(pl.level.name).Append("),"); } } From b75360efae01ec272bf9b36a4df2f4518fe9c8eb Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 3 Sep 2016 12:51:48 +1000 Subject: [PATCH 05/16] Fix notes logging minutes instead of months.. oops. --- Player/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Player/Player.cs b/Player/Player.cs index cfd6f879f..f77699ab0 100644 --- a/Player/Player.cs +++ b/Player/Player.cs @@ -575,7 +575,7 @@ namespace MCGalaxy { if (!Server.LogNotes) return; string src = who == null ? "(console)" : who.name; - string time = DateTime.UtcNow.ToString("dd/mm/yyyy"); + string time = DateTime.UtcNow.ToString("dd/MM/yyyy"); Server.Notes.Append(target + " " + type + " " + src + " " + time); } @@ -583,7 +583,7 @@ namespace MCGalaxy { if (!Server.LogNotes) return; string src = who == null ? "(console)" : who.name; - string time = DateTime.UtcNow.ToString("dd/mm/yyyy"); + string time = DateTime.UtcNow.ToString("dd/MM/yyyy"); reason = reason.Replace(" ", "%20"); Server.Notes.Append(target + " " + type + " " + src + " " + time + " " + reason); } From ae2806bed284c2c60dc4a1a2a68491b0ed0a1725 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 3 Sep 2016 14:57:08 +1000 Subject: [PATCH 06/16] Allow multiple realm owners for a map. --- Commands/CmdOverseer.cs | 12 +++++++++--- Commands/World/CmdMap.cs | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Commands/CmdOverseer.cs b/Commands/CmdOverseer.cs index 10ef155fa..a69d35221 100644 --- a/Commands/CmdOverseer.cs +++ b/Commands/CmdOverseer.cs @@ -104,8 +104,7 @@ namespace MCGalaxy.Commands { } void HandleMapCommand(Player p, string message, string cmd, string value) { - bool mapOnly = cmd == "PHYSICS" || cmd == "MOTD" || cmd == "GUNS" || cmd == "CHAT" || cmd == "RESTORE" || - cmd == "PERVISIT" || cmd == "TEXTURE" || cmd == "BUILDABLE" || cmd == "DELETEABLE"; + bool mapOnly = !(cmd == "ADD" || cmd == "DELETE" || cmd == "SAVE"); if (mapOnly && !OwnsMap(p, p.level)) { Player.Message(p, "You may only perform that action on your own map."); return; } @@ -339,8 +338,15 @@ namespace MCGalaxy.Commands { return p.name.ToLower(); } + static char[] splitChars = new [] { ',' }; static bool OwnsMap(Player p, Level lvl) { - return lvl.RealmOwner.CaselessEq(p.name) || p.level.name.CaselessStarts(p.name); + if (lvl.name.CaselessStarts(p.name)) return true; + string[] owners = lvl.RealmOwner.Replace(" ", "").Split(splitChars); + + foreach (string owner in owners) { + if (owner.CaselessEq(p.name)) return true; + } + return false; } public override void Help(Player p) { diff --git a/Commands/World/CmdMap.cs b/Commands/World/CmdMap.cs index bed7f5575..d043588ac 100644 --- a/Commands/World/CmdMap.cs +++ b/Commands/World/CmdMap.cs @@ -130,7 +130,7 @@ namespace MCGalaxy.Commands.World { case "realmowner": lvl.RealmOwner = value; if (value == "") Player.Message(p, "Removed realm owner for this level."); - else Player.Message(p, "Set realm owner of this level to {0}.", value); + else Player.Message(p, "Set realm owner/owners of this level to {0}.", value); break; default: Player.Message(p, "Could not find option entered."); return; From 1bc8d0d26ddf7a1fb07b5f3b6f1a357971be38af Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 3 Sep 2016 15:22:49 +1000 Subject: [PATCH 07/16] Don't show [yes] in /unloaded, makes it much less spammy. --- Commands/Information/CmdUnloaded.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Commands/Information/CmdUnloaded.cs b/Commands/Information/CmdUnloaded.cs index 8846edbcd..d5a3de2f0 100644 --- a/Commands/Information/CmdUnloaded.cs +++ b/Commands/Information/CmdUnloaded.cs @@ -47,7 +47,7 @@ namespace MCGalaxy.Commands { if (end == 0) { StringBuilder list = ListMaps(p, all, files, 0, files.Length); if (list.Length > 0) { - Player.Message(p, "Unloaded levels [Accessible]: "); + 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 { @@ -59,7 +59,7 @@ namespace MCGalaxy.Commands { StringBuilder list = ListMaps(p, all, files, start, end); if (list.Length > 0) { - Player.Message(p, "Unloaded levels [Accessible] (" + start + " to " + end + "):"); + 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"); @@ -78,8 +78,9 @@ namespace MCGalaxy.Commands { bool loadOnGoto; RetrieveProps(level, out visitP, out buildP, out loadOnGoto); - string visit = loadOnGoto && (p == null || p.Rank >= visitP) ? "%aYes" : "%cNo"; - builder.Append(", ").Append(Group.findPerm(buildP).color + level + " &b[" + visit + "&b]"); + 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; } From 405554960e7573d7bc6fbcce18e0db09db3e4e7b Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 3 Sep 2016 17:28:26 +1000 Subject: [PATCH 08/16] Fix /balance message showing globally, oops. --- Commands/Economy/CmdBalance.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Commands/Economy/CmdBalance.cs b/Commands/Economy/CmdBalance.cs index 937d79213..370a756b3 100644 --- a/Commands/Economy/CmdBalance.cs +++ b/Commands/Economy/CmdBalance.cs @@ -45,7 +45,7 @@ namespace MCGalaxy.Commands { } string targetName = PlayerInfo.GetColoredName(p, target); - Chat.MessageAll("Economy stats for {0}%S:", targetName); + Player.Message(p, "Economy stats for {0}%S:", targetName); Player.Message(p, " Current balance: &f{0} &3{1}", money, Server.moneys); Economy.EcoStats ecos = Economy.RetrieveStats(target); From 83896645411aa8f2b8258ede096d984f42364f5d Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 4 Sep 2016 11:12:26 +1000 Subject: [PATCH 09/16] Remove myself from the developers list. --- Uploads/devs.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Uploads/devs.txt b/Uploads/devs.txt index 92ebac7dc..5d5aa4eef 100644 --- a/Uploads/devs.txt +++ b/Uploads/devs.txt @@ -1,5 +1,4 @@ devs:Hetal+ mods:Good+ -devs:UnknownShadow200+ devs:venom983+ devs:UclCommander+ \ No newline at end of file From f03f601173f470ce383826bb044bc3dcb00f24a9 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 4 Sep 2016 19:54:19 +1000 Subject: [PATCH 10/16] Fix command.properties erroring if a line has trailing spaces by making it completely ignore spaces. --- Commands/Information/CmdWhoNick.cs | 4 ++-- Player/Group/GroupCommands.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Commands/Information/CmdWhoNick.cs b/Commands/Information/CmdWhoNick.cs index e6def6ec2..e5abc241f 100644 --- a/Commands/Information/CmdWhoNick.cs +++ b/Commands/Information/CmdWhoNick.cs @@ -22,7 +22,7 @@ namespace MCGalaxy.Commands { public sealed class CmdWhoNick : Command { public override string name { get { return "whonick"; } } - public override string shortcut { get { return ""; } } + public override string shortcut { get { return "realname"; } } public override string type { get { return CommandTypes.Information; } } public override bool museumUsable { get { return true; } } public override LevelPermission defaultRank { get { return LevelPermission.Guest; } } @@ -38,7 +38,7 @@ namespace MCGalaxy.Commands { } public override void Help(Player p) { - Player.Message(p, "%T/whonick "); + Player.Message(p, "%T/whonick [nickname]"); Player.Message(p, "%HDisplays the player's real username"); } } diff --git a/Player/Group/GroupCommands.cs b/Player/Group/GroupCommands.cs index 43de1c9fb..551ce2307 100644 --- a/Player/Group/GroupCommands.cs +++ b/Player/Group/GroupCommands.cs @@ -74,12 +74,12 @@ namespace MCGalaxy { } static void ReadVersion2(string[] lines, List cmdNames) { - string[] colon = new[] { " : " }; + char[] colon = new char[] { ':' }; foreach (string line in lines) { if (line == "" || line[0] == '#') continue; rankAllowance perms = new rankAllowance(); //Name : Lowest : Disallow : Allow - string[] args = line.Split(colon, StringSplitOptions.None); + string[] args = line.Replace(" ", "").Split(colon); if (!cmdNames.Contains(args[0])) { Server.s.Log("Incorrect command name: " + args[0]); continue; From 5157ac6a11a7b5edba1c2119d26ebacccb850fdf Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 4 Sep 2016 20:04:57 +1000 Subject: [PATCH 11/16] Tidy up the zombie survival UI a bit. --- Games/ZombieSurvival/ZombieGame.Game.cs | 2 +- Games/ZombieSurvival/ZombieGame.cs | 30 ++++++++++++------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Games/ZombieSurvival/ZombieGame.Game.cs b/Games/ZombieSurvival/ZombieGame.Game.cs index 5968b4b26..004a5284b 100644 --- a/Games/ZombieSurvival/ZombieGame.Game.cs +++ b/Games/ZombieSurvival/ZombieGame.Game.cs @@ -182,7 +182,7 @@ namespace MCGalaxy.Games { public override void PlayerMoneyChanged(Player p) { if (!Running || !p.level.name.CaselessEq(CurLevelName)) return; string moneyMsg = "&a" + p.money + " %S" + Server.moneys; - string stateMsg = " and you are " + (p.Game.Infected ? "&cdead" : "&aalive"); + string stateMsg = ", you are " + (p.Game.Infected ? "&cdead" : "&aalive"); p.SendCpeMessage(CpeMessageType.Status3, moneyMsg + stateMsg); } diff --git a/Games/ZombieSurvival/ZombieGame.cs b/Games/ZombieSurvival/ZombieGame.cs index fe71c6250..0fec168c3 100644 --- a/Games/ZombieSurvival/ZombieGame.cs +++ b/Games/ZombieSurvival/ZombieGame.cs @@ -16,13 +16,13 @@ or implied. See the Licenses for the specific language governing permissions and limitations under the Licenses. */ -using System; -using System.Collections.Generic; -using System.Data; -using System.IO; -using System.Threading; -using MCGalaxy.Commands; -using MCGalaxy.SQL; +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Threading; +using MCGalaxy.Commands; +using MCGalaxy.SQL; namespace MCGalaxy.Games { @@ -210,20 +210,20 @@ namespace MCGalaxy.Games { string GetStatusMessage(string timespan) { if (timespan.Length > 0) { - const string format = "&a{0} %Salive, &c{1} %Sinfected ({2})"; - return String.Format(format, Alive.Count, Infected.Count, timespan); + const string format = "&a{0} %Salive %S({2}, map: {1})"; + return String.Format(format, Alive.Count, CurLevelName, timespan); } else { - const string format = "&a{0} %Salive, &c{1} %Sinfected"; - return String.Format(format, Alive.Count, Infected.Count); + const string format = "&a{0} %Salive %S(map: {1})"; + return String.Format(format, Alive.Count, CurLevelName); } } string GetTimespan(int seconds) { if (seconds < 0) return ""; - if (seconds <= 10) return "10 secs left"; - if (seconds <= 30) return "30 secs left"; - if (seconds <= 60) return "1 min left"; - return ((seconds + 59) / 60) + " mins left"; + if (seconds <= 10) return "10s left"; + if (seconds <= 30) return "30s left"; + if (seconds <= 60) return "1m left"; + return ((seconds + 59) / 60) + "m left"; } static string[] defMessages = new string[] { "{0} WIKIWOO'D {1}", "{0} stuck their teeth into {1}", From 40cb0e0746a4068e0f25343fe782b58b943e032a Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 4 Sep 2016 20:08:16 +1000 Subject: [PATCH 12/16] Fiddle with zombie survival timings to be fairer to humans. --- Games/ZombieSurvival/ZombieGame.Core.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Games/ZombieSurvival/ZombieGame.Core.cs b/Games/ZombieSurvival/ZombieGame.Core.cs index 393a206f0..b385c8a2c 100644 --- a/Games/ZombieSurvival/ZombieGame.Core.cs +++ b/Games/ZombieSurvival/ZombieGame.Core.cs @@ -209,17 +209,19 @@ namespace MCGalaxy.Games { pKiller.Game.CurrentInfected++; pKiller.Game.TotalInfected++; pKiller.Game.MaxInfected = Math.Max(pKiller.Game.CurrentInfected, pKiller.Game.MaxInfected); + ShowInfectMessage(random, pAlive, pKiller); CheckHumanPledge(pAlive); CheckBounty(pAlive, pKiller); UpdatePlayerColor(pAlive, InfectCol); + Thread.Sleep(50); } } if (aliveChanged) alive = Alive.Items; } CheckInvisibilityTime(); - Thread.Sleep(25); + Thread.Sleep(200); } } From 1d8a4838acb966fc8f7f486b16f4ceafa1f13f80 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 4 Sep 2016 20:13:34 +1000 Subject: [PATCH 13/16] Reduce award saving overhead, make award saving threadsafe. --- Commands/Economy/CmdAward.cs | 7 ++++--- Commands/Economy/CmdAwardMod.cs | 5 +++-- Economy/Awards.cs | 21 ++++++++++++++------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Commands/Economy/CmdAward.cs b/Commands/Economy/CmdAward.cs index 17bec40ad..21b57ea3f 100644 --- a/Commands/Economy/CmdAward.cs +++ b/Commands/Economy/CmdAward.cs @@ -45,19 +45,20 @@ namespace MCGalaxy.Commands { if (!take) { if (Awards.GiveAward(plName, award)) { Chat.MessageAll("{0} %Swas awarded: &b{1}", - PlayerInfo.GetColoredName(p, plName), award); + PlayerInfo.GetColoredName(p, plName), award); + Awards.SavePlayers(); } else { Player.Message(p, "The player already has that award."); return; } } else { if (Awards.TakeAward(plName, award)) { Chat.MessageAll("{0} %Shad their &b{1} %Saward removed", - PlayerInfo.GetColoredName(p, plName), award); + PlayerInfo.GetColoredName(p, plName), award); + Awards.SavePlayers(); } else { Player.Message(p, "The player didn't have the award you tried to take"); return; } } - Awards.Save(); } public override void Help(Player p) { diff --git a/Commands/Economy/CmdAwardMod.cs b/Commands/Economy/CmdAwardMod.cs index e031df8e8..7aed7237c 100644 --- a/Commands/Economy/CmdAwardMod.cs +++ b/Commands/Economy/CmdAwardMod.cs @@ -41,15 +41,16 @@ namespace MCGalaxy.Commands { Player.Message(p, "This award already exists."); return; } else { Chat.MessageAll("Award added: &6{0} : {1}", args[0], args[1]); + Awards.SaveAwards(); } } else { if (!Awards.Remove(args[1])) { Player.Message(p, "This award does not exist."); return; } else { - Chat.MessageAll("Award removed: &6{0}", args[1]); + Chat.MessageAll("Award removed: &6{0}", args[1]); + Awards.SaveAwards(); } } - Awards.Save(); } public override void Help(Player p) { diff --git a/Economy/Awards.cs b/Economy/Awards.cs index a5a621b64..0354af683 100644 --- a/Economy/Awards.cs +++ b/Economy/Awards.cs @@ -54,7 +54,6 @@ namespace MCGalaxy { PropertiesFile.Read("text/awardsList.txt", AwardsListLineProcessor, ':'); PlayerAwards = new List(); PropertiesFile.Read("text/playerAwards.txt", PlayerAwardsLineProcessor, ':'); - Save(); } static void AwardsListLineProcessor(string key, string value) { @@ -76,8 +75,11 @@ namespace MCGalaxy { PlayerAwards.Add(pl); } - public static void Save() { - using (CP437Writer w = new CP437Writer("text/awardsList.txt")) { + static readonly object awardLock = new object(); + public static void SaveAwards() { + lock (awardLock) + using (CP437Writer w = new CP437Writer("text/awardsList.txt")) + { w.WriteLine("# This is a full list of awards. The server will load these and they can be awarded as you please"); w.WriteLine("# Format is:"); w.WriteLine("# AwardName : Description of award goes after the colon"); @@ -85,10 +87,15 @@ namespace MCGalaxy { foreach (Award award in AwardsList) w.WriteLine(award.Name + " : " + award.Description); } - - using (StreamWriter w = new StreamWriter("text/playerAwards.txt")) { + } + + static readonly object playerLock = new object(); + public static void SavePlayers() { + lock (playerLock) + using (StreamWriter w = new StreamWriter("text/playerAwards.txt")) + { foreach (PlayerAward pA in PlayerAwards) - w.WriteLine(pA.Name.ToLower() + " : " + pA.Awards.Join(",")); + w.WriteLine(pA.Name.ToLower() + " : " + pA.Awards.Join(",")); } } #endregion @@ -107,7 +114,7 @@ namespace MCGalaxy { pl.Awards.Add(name); return true; } - + PlayerAward newPl; newPl.Name = playerName; newPl.Awards = new List(); From e12500c264a30c28fc731b6b5240da480369b248 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 4 Sep 2016 20:43:59 +1000 Subject: [PATCH 14/16] Remove awards for zombie survival, they didn't even work. --- Economy/ZombieItems.cs | 1 - GUI/Settings/ZombieProperties.cs | 9 +--- Games/ZombieSurvival/ZombieAwards.cs | 62 ------------------------- Games/ZombieSurvival/ZombieGame.Core.cs | 26 ----------- Games/ZombieSurvival/ZombieGame.cs | 5 -- MCGalaxy_.csproj | 1 - 6 files changed, 1 insertion(+), 103 deletions(-) delete mode 100644 Games/ZombieSurvival/ZombieAwards.cs diff --git a/Economy/ZombieItems.cs b/Economy/ZombieItems.cs index 1267cd907..cf48eb179 100644 --- a/Economy/ZombieItems.cs +++ b/Economy/ZombieItems.cs @@ -68,7 +68,6 @@ namespace MCGalaxy.Eco { if (map == null) return; Command.all.Find("queue").Use(p, "level " + map); - ZombieAwards.Give(p, ZombieAwards.buyQueue, Server.zombie); Economy.MakePurchase(p, Price, "%3QueueLevel: " + map); } } diff --git a/GUI/Settings/ZombieProperties.cs b/GUI/Settings/ZombieProperties.cs index 432f1270d..4a867f305 100644 --- a/GUI/Settings/ZombieProperties.cs +++ b/GUI/Settings/ZombieProperties.cs @@ -74,12 +74,7 @@ namespace MCGalaxy.Gui { [Description("Whether zombie survival should start when the server starts.")] [Category("General settings")] [DisplayName("Start immediately")] - public bool StartImmediately { get; set; } - - [Description("Whether awards should be given for various events/actions in zombie survival. ")] - [Category("General settings")] - [DisplayName("Use awards")] - public bool UseAwards { get; set; } + public bool StartImmediately { get; set; } [Description("Max distance players are allowed to move between packets (for speedhack detection). " + @@ -179,7 +174,6 @@ namespace MCGalaxy.Gui { Respawning = !ZombieGame.noRespawn; SetMainLevel = ZombieGame.SetMainLevel; StartImmediately = ZombieGame.StartImmediately; - UseAwards = ZombieGame.UseAwards; MaxMoveDistance = ZombieGame.MaxMoveDistance; HitboxPrecision = ZombieGame.HitboxPrecision; @@ -217,7 +211,6 @@ namespace MCGalaxy.Gui { ZombieGame.noRespawn = !Respawning; ZombieGame.SetMainLevel = SetMainLevel; ZombieGame.StartImmediately = StartImmediately; - ZombieGame.UseAwards = UseAwards; ZombieGame.MaxMoveDistance = MaxMoveDistance; ZombieGame.HitboxPrecision = HitboxPrecision; diff --git a/Games/ZombieSurvival/ZombieAwards.cs b/Games/ZombieSurvival/ZombieAwards.cs deleted file mode 100644 index cbf869f1f..000000000 --- a/Games/ZombieSurvival/ZombieAwards.cs +++ /dev/null @@ -1,62 +0,0 @@ -/* - 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; - -namespace MCGalaxy.Games { - - public static class ZombieAwards { - - internal const string buyQueue = "Wishes"; - internal const string infectedEnd = "Unlucky"; - internal const string onlyHuman = "Can't touch this"; - internal const string killLastHuman = "Finisher"; - internal const string killInvisHuman = "The sixth sense"; - internal const string killHumanTwice = "Deja Vu"; - internal const string reviveSurvive = "Second Chance"; - internal const string survive5Rounds = "Bear Grylls"; - internal const string luckyNumber7 = "Lucky Number 7"; - internal const string lowWinChance = "Impossible"; - internal const string starKiller = "Dream destroyer"; - internal const string afkKiller = "Assassin"; - internal const string humanKiller = "Chuck Norris"; - - public static void AddDefaults() { - Awards.Add(buyQueue, "Buy a queue level"); - Awards.Add(infectedEnd, "Get infected in last 5 seconds of a round"); - Awards.Add(onlyHuman, "Be the sole human survivor"); - Awards.Add(killLastHuman, "Infect the last human left"); - Awards.Add(killInvisHuman, "Infect a human who is invisible"); - Awards.Add(killHumanTwice, "Infect a human twice in the same round"); - Awards.Add(reviveSurvive, "Survive a round after using a revive"); - Awards.Add(survive5Rounds, "Survive 5 rounds in a row"); - Awards.Add(luckyNumber7, "Win lottery when exactly 7 players joined it"); - Awards.Add(lowWinChance, "Survive on a map with a win chance of 10% or les"); - Awards.Add(starKiller, "Kill a human with a golden star."); - Awards.Add(afkKiller, "Infect an auto-afk human"); - Awards.Add(humanKiller, "Infect 10 humans in a row"); - } - - public static void Give(Player p, string award, ZombieGame game) { - Server.s.Log("AWARD: " +award + "," + p.name); - if (!ZombieGame.UseAwards) return; - bool awarded = Awards.GiveAward(p.name, award); - if (awarded && game.CurLevel != null) - game.CurLevel.ChatLevel(p.ColoredName + " %Searned the achievement &a" + award); - } - } -} diff --git a/Games/ZombieSurvival/ZombieGame.Core.cs b/Games/ZombieSurvival/ZombieGame.Core.cs index b385c8a2c..e6911d884 100644 --- a/Games/ZombieSurvival/ZombieGame.Core.cs +++ b/Games/ZombieSurvival/ZombieGame.Core.cs @@ -186,7 +186,6 @@ namespace MCGalaxy.Games { && pKiller.level.name.CaselessEq(CurLevelName) && pAlive.level.name.CaselessEq(CurLevelName)) { - CheckKillerAwards(pAlive, pKiller); InfectPlayer(pAlive); pAlive.Game.LastInfecter = pKiller.name; aliveChanged = true; @@ -199,8 +198,6 @@ namespace MCGalaxy.Games { pKiller.SetMoney(pKiller.money + (2 + infectCombo)); CurLevel.ChatLevel(pKiller.ColoredName + " is on a rampage! " + (infectCombo + 1) + " infections in a row!"); } - if (infectCombo == 10) - ZombieAwards.Give(pKiller, ZombieAwards.humanKiller, this); } else { infectCombo = 0; } @@ -274,19 +271,6 @@ namespace MCGalaxy.Games { } } - void CheckKillerAwards(Player pAlive, Player pKiller) { - if (pAlive.IsAfk) - ZombieAwards.Give(pKiller, ZombieAwards.afkKiller, this); - if (pAlive.Game.Invisible) - ZombieAwards.Give(pKiller, ZombieAwards.killInvisHuman, this); - if (pAlive.Game.CurrentRoundsSurvived >= 3) - ZombieAwards.Give(pKiller, ZombieAwards.starKiller, this); - if (Alive.Count == 1) - ZombieAwards.Give(pKiller, ZombieAwards.killLastHuman, this); - if (pAlive.Game.LastInfecter == pKiller.name) - ZombieAwards.Give(pKiller, ZombieAwards.killHumanTwice, this); - } - void ShowInfectMessage(Random random, Player pAlive, Player pKiller) { string text = null; List infectMsgs = pKiller.Game.InfectMessages; @@ -332,22 +316,14 @@ namespace MCGalaxy.Games { } else { int winChance = CurLevel.WinChance; CurLevel.RoundsHumanWon++; - if (alive.Length == 1) - ZombieAwards.Give(alive[0], ZombieAwards.onlyHuman, this); foreach (Player pl in alive) { if (pl.Game.PledgeSurvive) { pl.SendMessage("You received &a5 %3" + Server.moneys + "%S for successfully pledging that you would survive."); pl.SetMoney(pl.money + 5); } - if (winChance <= 10) - ZombieAwards.Give(pl, ZombieAwards.lowWinChance, this); - if (pl.Game.RevivesUsed > 0) - ZombieAwards.Give(pl, ZombieAwards.reviveSurvive, this); pl.Game.CurrentRoundsSurvived++; - if (pl.Game.CurrentRoundsSurvived == 5) - ZombieAwards.Give(pl, ZombieAwards.survive5Rounds, this); pl.Game.TotalRoundsSurvived++; pl.Game.MaxRoundsSurvived = Math.Max(pl.Game.CurrentRoundsSurvived, pl.Game.MaxRoundsSurvived); ResetPlayer(pl, ref playersString); @@ -412,8 +388,6 @@ namespace MCGalaxy.Games { } Lottery.Clear(); winner.SetMoney(winner.money + 10); - if (online.Count == 7) - ZombieAwards.Give(winner, ZombieAwards.luckyNumber7, this); } int GetReward(Player pl, Player[] alive, Random rand) { diff --git a/Games/ZombieSurvival/ZombieGame.cs b/Games/ZombieSurvival/ZombieGame.cs index 0fec168c3..7ef8d4b89 100644 --- a/Games/ZombieSurvival/ZombieGame.cs +++ b/Games/ZombieSurvival/ZombieGame.cs @@ -39,7 +39,6 @@ namespace MCGalaxy.Games { RoundsDone = 0; if (!SetStartLevel(level)) return; - if (UseAwards) ZombieAwards.AddDefaults(); Thread t = new Thread(MainLoop); t.Name = "MCG_ZombieGame"; t.Start(); @@ -102,10 +101,6 @@ namespace MCGalaxy.Games { p.SetPrefix(); ResetInvisibility(p); - int delta = (int)(RoundEnd - DateTime.UtcNow).TotalSeconds; - if (delta >= 0 && delta <= 5) - ZombieAwards.Give(p, ZombieAwards.infectedEnd, this); - p.Game.Infected = true; p.Game.TimeInfected = DateTime.UtcNow; UpdatePlayerColor(p, Colors.red); diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index 295e800b4..dc42e38b8 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -482,7 +482,6 @@ - From df0bf301f2a7df2235ceec58b63ce1b6575ee676 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 4 Sep 2016 21:58:44 +1000 Subject: [PATCH 15/16] Fix -hax not working if color in the motd. --- Levels/Hacks.cs | 1 + Network/Player.Networking.cs | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Levels/Hacks.cs b/Levels/Hacks.cs index 060abfa1a..314f6a942 100644 --- a/Levels/Hacks.cs +++ b/Levels/Hacks.cs @@ -31,6 +31,7 @@ namespace MCGalaxy { public static byte[] MakeHackControl(Player p) { string motd = p.level.GetMotd(p); + motd = Colors.StripColors(motd); bool isOp = p.Rank >= LevelPermission.Operator; bool fly = true, noclip = true, speed = true, respawn = true, _3rdPerson = true; diff --git a/Network/Player.Networking.cs b/Network/Player.Networking.cs index 2ac6411d7..abb57e9db 100644 --- a/Network/Player.Networking.cs +++ b/Network/Player.Networking.cs @@ -300,8 +300,10 @@ namespace MCGalaxy { if (OnSendMOTD != null) OnSendMOTD(this, packet); Send(packet); - if (HasCpeExt(CpeExt.HackControl)) - Send(Hacks.MakeHackControl(this)); + if (!HasCpeExt(CpeExt.HackControl)) return; + Send(Hacks.MakeHackControl(this)); + if (Game.Referee) + Send(Packet.MakeHackControl(true, true, true, true, true, -1)); } public void SendMap(Level oldLevel) { SendRawMap(oldLevel, level); } From 7f6a451530fba3ba4eaa090be6488a5cadc9608a Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 4 Sep 2016 23:30:02 +1000 Subject: [PATCH 16/16] Fix join message showing for first round of zombie survival. --- Commands/World/CmdGoto.cs | 3 +-- Levels/Level.cs | 7 +++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Commands/World/CmdGoto.cs b/Commands/World/CmdGoto.cs index 6a8ff77aa..2ae91fe39 100644 --- a/Commands/World/CmdGoto.cs +++ b/Commands/World/CmdGoto.cs @@ -116,8 +116,7 @@ namespace MCGalaxy.Commands.World { CheckGamesJoin(p, oldLevel); p.prevMsg = ""; - bool showJoin = p.level.ShouldSaveChanges() || (oldLevel != null && oldLevel.ShouldSaveChanges()); - if (!p.hidden && showJoin) { + if (!p.hidden && p.level.ShouldShowJoinMessage(oldLevel)) { Player.SendChatFrom(p, p.color + "*" + p.DisplayName + " %Swent to &b" + lvl.name, false); Player.RaisePlayerAction(p, PlayerAction.JoinWorld, lvl.name); } diff --git a/Levels/Level.cs b/Levels/Level.cs index 4c383eae9..461c2b2c1 100644 --- a/Levels/Level.cs +++ b/Levels/Level.cs @@ -127,6 +127,13 @@ namespace MCGalaxy { return true; } + public bool ShouldShowJoinMessage(Level prev) { + if (Server.zombie.Running && name.CaselessEq(Server.zombie.CurLevelName) + && (prev == this || prev.name.CaselessEq(Server.zombie.LastLevelName))) return false; + if (Server.lava.active && Server.lava.HasMap(name)) return false; + return true; + } + /// The currently active game running on this map, /// or null if there is no game running. public IGame CurrentGame() {