diff --git a/GUI/PropertyWindow/GamesHelper.cs b/GUI/PropertyWindow/GamesHelper.cs index 33a886ff4..fd50b43c1 100644 --- a/GUI/PropertyWindow/GamesHelper.cs +++ b/GUI/PropertyWindow/GamesHelper.cs @@ -119,6 +119,12 @@ namespace MCGalaxy.Gui { } + public void UpdateMapConfig(string map) { + if (game.Running && game.Map.name == map) { + game.UpdateMapConfig(); + } + } + public void UpdateMaps() { UpdateUsedMaps(); UpdateNotUsedMaps(null); diff --git a/GUI/PropertyWindow/PropertyWindow.Games.cs b/GUI/PropertyWindow/PropertyWindow.Games.cs index 0764b0f6c..2d33077d8 100644 --- a/GUI/PropertyWindow/PropertyWindow.Games.cs +++ b/GUI/PropertyWindow/PropertyWindow.Games.cs @@ -193,12 +193,9 @@ namespace MCGalaxy.Gui { lsCurCfg.RoundTime = ls_numRound.Value; lsCurCfg.FloodTime = ls_numFlood.Value; lsCurCfg.LayerInterval = ls_numLayerTime.Value; - lsCurCfg.Save(lsCurMap); - LSGame game = LSGame.Instance; - if (game.Running && game.Map.name == lsCurMap) { - game.UpdateMapConfig(); - } + lsCurCfg.Save(lsCurMap); + lsHelper.UpdateMapConfig(lsCurMap); } @@ -276,12 +273,9 @@ namespace MCGalaxy.Gui { twCurCfg.GracePeriodTime = tw_numGrace.Value; twCurCfg.BalanceTeams = tw_cbBalance.Checked; twCurCfg.TeamKills = tw_cbKills.Checked; - twCurCfg.Save(twCurMap); - TWGame game = TWGame.Instance; - if (game.Running && game.Map.name == twCurMap) { - game.UpdateMapConfig(); - } + twCurCfg.Save(twCurMap); + twHelper.UpdateMapConfig(twCurMap); } void tw_btnAbout_Click(object sender, EventArgs e) { diff --git a/MCGalaxy/Commands/Fun/CTF/CmdCtf.cs b/MCGalaxy/Commands/Fun/CTF/CmdCtf.cs index 8145f14c3..9e31f194e 100644 --- a/MCGalaxy/Commands/Fun/CTF/CmdCtf.cs +++ b/MCGalaxy/Commands/Fun/CTF/CmdCtf.cs @@ -16,8 +16,6 @@ permissions and limitations under the Licenses. */ using System; -using System.Collections.Generic; -using System.IO; using MCGalaxy.Games; using MCGalaxy.Maths; using BlockID = System.UInt16; @@ -33,33 +31,34 @@ namespace MCGalaxy.Commands.Fun { protected override void HandleSet(Player p, RoundsGame game, string[] args) { string prop = args[1]; - CTFMapConfig cfg = RetrieveConfig(p); + CTFMapConfig cfg = new CTFMapConfig(); + LoadMapConfig(p, cfg); if (prop.CaselessEq("bluespawn")) { cfg.BlueSpawn = (Vec3U16)p.Pos.FeetBlockCoords; p.Message("Set spawn of blue team to &b" + cfg.BlueSpawn); - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); } else if (prop.CaselessEq("redspawn")) { cfg.RedSpawn = (Vec3U16)p.Pos.FeetBlockCoords; p.Message("Set spawn of red team to &b" + cfg.RedSpawn); - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); } else if (prop.CaselessEq("blueflag")) { p.Message("Place or delete a block to set blue team's flag."); - p.MakeSelection(1, null, BlueFlagCallback); + p.MakeSelection(1, cfg, BlueFlagCallback); } else if (prop.CaselessEq("redflag")) { p.Message("Place or delete a block to set red team's flag."); - p.MakeSelection(1, null, RedFlagCallback); + p.MakeSelection(1, cfg, RedFlagCallback); } else if (prop.CaselessEq("divider")) { cfg.ZDivider = p.Pos.BlockZ; p.Message("Set Z line divider to {0}.", cfg.ZDivider); - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); } else { Help(p, "set"); } } - static bool BlueFlagCallback(Player p, Vec3S32[] marks, object state, BlockID block) { - CTFMapConfig cfg = RetrieveConfig(p); + bool BlueFlagCallback(Player p, Vec3S32[] marks, object state, BlockID block) { + CTFMapConfig cfg = (CTFMapConfig)state; Vec3U16 P = (Vec3U16)marks[0]; cfg.BlueFlagPos = P; p.Message("Set flag position of blue team to ({0})", P); @@ -69,12 +68,12 @@ namespace MCGalaxy.Commands.Fun { cfg.BlueFlagBlock = block; p.Message("Set flag block of blue team to {0}", Block.GetName(p, block)); - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); return false; } - static bool RedFlagCallback(Player p, Vec3S32[] marks, object state, BlockID block) { - CTFMapConfig cfg = RetrieveConfig(p); + bool RedFlagCallback(Player p, Vec3S32[] marks, object state, BlockID block) { + CTFMapConfig cfg = (CTFMapConfig)state; Vec3U16 P = (Vec3U16)marks[0]; cfg.RedFlagPos = P; p.Message("Set flag position of red team to ({0})", P); @@ -84,17 +83,10 @@ namespace MCGalaxy.Commands.Fun { cfg.RedFlagBlock = block; p.Message("Set flag block of red team to {0}", Block.GetName(p, block)); - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); return false; } - static CTFMapConfig RetrieveConfig(Player p) { - CTFMapConfig cfg = new CTFMapConfig(); - cfg.SetDefaults(p.level); - cfg.Load(p.level.name); - return cfg; - } - static void UpdateConfig(Player p, CTFMapConfig cfg) { cfg.Save(p.level.name); if (p.level == CTFGame.Instance.Map) CTFGame.Instance.UpdateMapConfig(); diff --git a/MCGalaxy/Commands/Fun/CmdLavaSurvival.cs b/MCGalaxy/Commands/Fun/CmdLavaSurvival.cs index 19d7e5c04..93ca4f3f2 100644 --- a/MCGalaxy/Commands/Fun/CmdLavaSurvival.cs +++ b/MCGalaxy/Commands/Fun/CmdLavaSurvival.cs @@ -17,7 +17,6 @@ permissions and limitations under the Licenses. */ using System; -using System.Collections.Generic; using MCGalaxy.Games; using MCGalaxy.Maths; using BlockID = System.UInt16; @@ -33,12 +32,15 @@ namespace MCGalaxy.Commands.Fun { protected override void HandleSet(Player p, RoundsGame game, string[] args) { string prop = args[1]; + LSMapConfig cfg = new LSMapConfig(); + LoadMapConfig(p, cfg); + if (prop.CaselessEq("spawn")) { - HandleSetSpawn(p, args); + HandleSetSpawn(p, args, cfg); } else if (prop.CaselessEq("block")) { - HandleSetBlock(p, args); + HandleSetBlock(p, args, cfg); } else if (prop.CaselessEq("other")) { - HandleSetOther(p, args); + HandleSetOther(p, args, cfg); } else { Help(p, "set"); } @@ -57,8 +59,7 @@ namespace MCGalaxy.Commands.Fun { } - void HandleSetSpawn(Player p, string[] args) { - LSMapConfig cfg = RetrieveConfig(p); + void HandleSetSpawn(Player p, string[] args, LSMapConfig cfg) { if (args.Length < 3) { p.Message("Flood position: &b" + cfg.FloodPos); p.Message("Layer position: &b" + cfg.LayerPos); @@ -94,29 +95,28 @@ namespace MCGalaxy.Commands.Fun { Help(p, "spawn"); } - if (ok) UpdateConfig(p, cfg); + if (ok) SaveMapConfig(p, cfg); } - static bool SetFloodPos(Player p, Vec3S32[] m, object state, BlockID block) { + bool SetFloodPos(Player p, Vec3S32[] m, object state, BlockID block) { LSMapConfig cfg = (LSMapConfig)state; cfg.FloodPos = (Vec3U16)m[0]; - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); p.Message("Flood position set to &b({0})", m[0]); return false; } - static bool SetLayerPos(Player p, Vec3S32[] m, object state, BlockID block) { + bool SetLayerPos(Player p, Vec3S32[] m, object state, BlockID block) { LSMapConfig cfg = (LSMapConfig)state; cfg.LayerPos = (Vec3U16)m[0]; - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); p.Message("Layer position set to &b({0})", m[0]); return false; } - void HandleSetBlock(Player p, string[] args) { - LSMapConfig cfg = RetrieveConfig(p); + void HandleSetBlock(Player p, string[] args, LSMapConfig cfg) { if (args.Length < 3) { p.Message("Fast lava chance: &b" + cfg.FastChance + "%"); p.Message("Killer lava/water chance: &b" + cfg.KillerChance + "%"); @@ -141,11 +141,10 @@ namespace MCGalaxy.Commands.Fun { Help(p, "block"); } - if (ok) UpdateConfig(p, cfg); + if (ok) SaveMapConfig(p, cfg); } - void HandleSetOther(Player p, string[] args) { - LSMapConfig cfg = RetrieveConfig(p); + void HandleSetOther(Player p, string[] args, LSMapConfig cfg) { if (args.Length < 3) { p.Message("Layer time: &b" + cfg.LayerInterval.Shorten(true)); p.Message("Round time: &b" + cfg.RoundTime.Shorten(true)); @@ -174,31 +173,19 @@ namespace MCGalaxy.Commands.Fun { Help(p, "other"); } - if (ok) UpdateConfig(p, cfg); + if (ok) SaveMapConfig(p, cfg); } - static bool SetSafeZone(Player p, Vec3S32[] m, object state, BlockID block) { + bool SetSafeZone(Player p, Vec3S32[] m, object state, BlockID block) { LSMapConfig cfg = (LSMapConfig)state; cfg.SafeZoneMin = (Vec3U16)Vec3S32.Min(m[0], m[1]); cfg.SafeZoneMax = (Vec3U16)Vec3S32.Max(m[0], m[1]); - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); p.Message("Safe zone set! &b({0}) ({1})", cfg.SafeZoneMin, cfg.SafeZoneMax); return false; } - static LSMapConfig RetrieveConfig(Player p) { - LSMapConfig cfg = new LSMapConfig(); - cfg.SetDefaults(p.level); - cfg.Load(p.level.name); - return cfg; - } - - static void UpdateConfig(Player p, LSMapConfig cfg) { - cfg.Save(p.level.name); - if (p.level == LSGame.Instance.Map) LSGame.Instance.UpdateMapConfig(); - } - public override void Help(Player p, string message) { if (message.CaselessEq("set")) { p.Message("%T/Help LS spawn %H- Views help for lava spawn settings"); diff --git a/MCGalaxy/Commands/Fun/CmdTntWars.cs b/MCGalaxy/Commands/Fun/CmdTntWars.cs index 3aef28be2..fcf39d8ec 100644 --- a/MCGalaxy/Commands/Fun/CmdTntWars.cs +++ b/MCGalaxy/Commands/Fun/CmdTntWars.cs @@ -17,7 +17,6 @@ */ using System; using System.Collections.Generic; -using System.Threading; using MCGalaxy.Games; using MCGalaxy.Maths; using BlockID = System.UInt16; @@ -56,9 +55,10 @@ namespace MCGalaxy.Commands.Fun { protected override void HandleSet(Player p, RoundsGame game_, string[] args) { TWGame game = (TWGame)game_; - TWMapConfig cfg = RetrieveConfig(p); + TWMapConfig cfg = new TWMapConfig(); TWConfig gameCfg = TWGame.Config; + LoadMapConfig(p, cfg); if (args.Length == 1) { Help(p, "set"); return; } if (args.Length == 2) { OutputStatus(p, gameCfg, cfg); return; } @@ -134,7 +134,7 @@ namespace MCGalaxy.Commands.Fun { } else { OutputStatus(p, gameCfg, cfg); return; } - UpdateConfig(p, cfg); + SaveMapConfig(p, cfg); } static void OutputStatus(Player p, TWConfig gameCfg, TWMapConfig cfg) { @@ -290,18 +290,6 @@ namespace MCGalaxy.Commands.Fun { p.Message("TNT Wars: {0} is now {1}", name, GetBool(target)); } - static TWMapConfig RetrieveConfig(Player p) { - TWMapConfig cfg = new TWMapConfig(); - cfg.SetDefaults(p.level); - cfg.Load(p.level.name); - return cfg; - } - - static void UpdateConfig(Player p, TWMapConfig cfg) { - cfg.Save(p.level.name); - if (p.level == TWGame.Instance.Map) TWGame.Instance.UpdateMapConfig(); - } - public override void Help(Player p, string message) { if (message.CaselessEq("set")) { diff --git a/MCGalaxy/Commands/Fun/RoundsGameCmd.cs b/MCGalaxy/Commands/Fun/RoundsGameCmd.cs index 423cd468d..0f3f5a4cd 100644 --- a/MCGalaxy/Commands/Fun/RoundsGameCmd.cs +++ b/MCGalaxy/Commands/Fun/RoundsGameCmd.cs @@ -93,5 +93,16 @@ namespace MCGalaxy.Commands.Fun { } protected abstract void HandleSet(Player p, RoundsGame game, string[] args); + + protected void LoadMapConfig(Player p, RoundsGameMapConfig cfg) { + cfg.SetDefaults(p.level); + cfg.Load(p.level.name); + } + + protected void SaveMapConfig(Player p, RoundsGameMapConfig cfg) { + RoundsGame game = Game; + cfg.Save(p.level.name); + if (p.level == game.Map) game.UpdateMapConfig(); + } } } diff --git a/MCGalaxy/Games/CTF/CtfConfig.cs b/MCGalaxy/Games/CTF/CtfConfig.cs index 25f513871..ec869b2a2 100644 --- a/MCGalaxy/Games/CTF/CtfConfig.cs +++ b/MCGalaxy/Games/CTF/CtfConfig.cs @@ -31,7 +31,7 @@ namespace MCGalaxy.Games { protected override string PropsPath { get { return "properties/ctf.properties"; } } } - public sealed class CTFMapConfig { + public sealed class CTFMapConfig : RoundsGameMapConfig { [ConfigVec3("red-spawn", null)] public Vec3U16 RedSpawn; [ConfigVec3("red-pos", null)] public Vec3U16 RedFlagPos; [ConfigBlock("red-block", null, Block.Air)] @@ -57,22 +57,18 @@ namespace MCGalaxy.Games { const string propsDir = "properties/CTF/"; - static string Path(string map) { return propsDir + map + ".properties"; } static ConfigElement[] cfg; - - public void Load(string map) { + public override void Load(string map) { if (cfg == null) cfg = ConfigElement.GetAll(typeof(CTFMapConfig)); - ConfigElement.ParseFile(cfg, Path(map), this); + LoadFrom(cfg, propsDir, map); } - public void Save(string map) { - if (!Directory.Exists(propsDir)) Directory.CreateDirectory(propsDir); - + public override void Save(string map) { if (cfg == null) cfg = ConfigElement.GetAll(typeof(CTFMapConfig)); - ConfigElement.SerialiseSimple(cfg, Path(map), this); + SaveTo(cfg, propsDir, map); } - public void SetDefaults(Level lvl) { + public override void SetDefaults(Level lvl) { ZDivider = lvl.Length / 2; RedFlagBlock = Block.Red; BlueFlagBlock = Block.Blue; diff --git a/MCGalaxy/Games/LavaSurvival/LSConfig.cs b/MCGalaxy/Games/LavaSurvival/LSConfig.cs index e80d5415f..ff7a64246 100644 --- a/MCGalaxy/Games/LavaSurvival/LSConfig.cs +++ b/MCGalaxy/Games/LavaSurvival/LSConfig.cs @@ -35,7 +35,7 @@ namespace MCGalaxy.Games { protected override string PropsPath { get { return "properties/lavasurvival.properties"; } } } - public sealed class LSMapConfig { + public sealed class LSMapConfig : RoundsGameMapConfig { [ConfigInt("fast-chance", null, 0, 0, 100)] public int FastChance; [ConfigInt("killer-chance", null, 100, 0, 100)] @@ -66,22 +66,18 @@ namespace MCGalaxy.Games { const string propsDir = "properties/lavasurvival/"; - static string Path(string map) { return propsDir + map + ".properties"; } - static ConfigElement[] cfg; - - public void Load(string map) { + static ConfigElement[] cfg; + public override void Load(string map) { if (cfg == null) cfg = ConfigElement.GetAll(typeof(LSMapConfig)); - ConfigElement.ParseFile(cfg, Path(map), this); + LoadFrom(cfg, propsDir, map); } - public void Save(string map) { - if (!Directory.Exists(propsDir)) Directory.CreateDirectory(propsDir); - + public override void Save(string map) { if (cfg == null) cfg = ConfigElement.GetAll(typeof(LSMapConfig)); - ConfigElement.SerialiseSimple(cfg, Path(map), this); + SaveTo(cfg, propsDir, map); } - public void SetDefaults(Level lvl) { + public override void SetDefaults(Level lvl) { ushort x = (ushort)(lvl.Width / 2), y = (ushort)(lvl.Height / 2), z = (ushort)(lvl.Length / 2); FloodPos = new Vec3U16(x, (ushort)(lvl.Height - 1), z); LayerPos = new Vec3U16(0, y , 0); diff --git a/MCGalaxy/Games/RoundsGame/RoundsGame.cs b/MCGalaxy/Games/RoundsGame/RoundsGame.cs index 1c5c05a51..0a23a6a33 100644 --- a/MCGalaxy/Games/RoundsGame/RoundsGame.cs +++ b/MCGalaxy/Games/RoundsGame/RoundsGame.cs @@ -30,12 +30,19 @@ namespace MCGalaxy.Games { public string LastMap = ""; public LevelPicker Picker; + /// Messages general info about current round and players. + /// e.g. who is alive, points of each team, etc. public abstract void OutputStatus(Player p); + /// The instance of this game's overall configuration object. public abstract RoundsGameConfig GetConfig(); + /// Updates state from the map specific configuration file. public abstract void UpdateMapConfig(); + /// Runs a single round of this game. protected abstract void DoRound(); + /// Gets the list of all players in this game. protected abstract List GetPlayers(); + /// Saves stats to the database for the given player. protected virtual void SaveStats(Player pl) { } protected abstract void StartGame(); @@ -69,6 +76,7 @@ namespace MCGalaxy.Games { t.Start(); } + /// Attempts to auto start this game with infinite rounds. public void AutoStart() { if (!GetConfig().StartImmediately) return; try { diff --git a/MCGalaxy/Games/RoundsGame/RoundsGameConfig.cs b/MCGalaxy/Games/RoundsGame/RoundsGameConfig.cs index f83f9f0ba..aea786540 100644 --- a/MCGalaxy/Games/RoundsGame/RoundsGameConfig.cs +++ b/MCGalaxy/Games/RoundsGame/RoundsGameConfig.cs @@ -17,6 +17,7 @@ */ using System; using System.Collections.Generic; +using System.IO; using MCGalaxy.Config; using MCGalaxy.Events.GameEvents; using MCGalaxy.Events.LevelEvents; @@ -26,6 +27,30 @@ using MCGalaxy.Network; namespace MCGalaxy.Games { + /// Stores map-specific game configuration state. + public abstract class RoundsGameMapConfig { + + protected void LoadFrom(ConfigElement[] cfg, string propsDir, string map) { + string path = propsDir + map + ".properties"; + ConfigElement.ParseFile(cfg, path, this); + } + + protected void SaveTo(ConfigElement[] cfg, string propsDir, string map) { + string path = propsDir + map + ".properties"; + if (!Directory.Exists(propsDir)) Directory.CreateDirectory(propsDir); + ConfigElement.SerialiseSimple(cfg, path, this); + } + + /// Saves this configuration to disc. + public abstract void Save(string map); + /// Loads this configuration from disc. + public abstract void Load(string map); + /// Applies default values for config fields which differ per map. + /// e.g. spawn positions, zones + public abstract void SetDefaults(Level lvl); + } + + /// Stores overall game configuration state. public abstract class RoundsGameConfig { [ConfigBool("start-on-server-start", "Game", false)] public bool StartImmediately; @@ -36,6 +61,8 @@ namespace MCGalaxy.Games { [ConfigStringList("maps", "Game")] public List Maps = new List(); + /// Whether users are allowed to auto-join maps used by this game. + /// If false, users can only join these maps when manually /load ed. public abstract bool AllowAutoload { get; } protected abstract string PropsPath { get; } protected abstract string GameName { get; } diff --git a/MCGalaxy/Games/TntWars/TWConfig.cs b/MCGalaxy/Games/TntWars/TWConfig.cs index 9bcf7e7c5..88c0d9ce4 100644 --- a/MCGalaxy/Games/TntWars/TWConfig.cs +++ b/MCGalaxy/Games/TntWars/TWConfig.cs @@ -38,7 +38,7 @@ namespace MCGalaxy.Games { public TWDifficulty Difficulty = TWDifficulty.Normal; } - public sealed class TWMapConfig { + public sealed class TWMapConfig : RoundsGameMapConfig { [ConfigBool("grace-period", null, true)] public bool GracePeriod = true; @@ -75,22 +75,18 @@ namespace MCGalaxy.Games { [ConfigVec3("blue-spawn", null)] public Vec3U16 BlueSpawn; const string propsDir = "properties/tntwars/"; - static string Path(string map) { return propsDir + map + ".properties"; } - static ConfigElement[] cfg; - - public void Load(string map) { + static ConfigElement[] cfg; + public override void Load(string map) { if (cfg == null) cfg = ConfigElement.GetAll(typeof(TWMapConfig)); - ConfigElement.ParseFile(cfg, Path(map), this); + LoadFrom(cfg, propsDir, map); } - public void Save(string map) { - if (!Directory.Exists(propsDir)) Directory.CreateDirectory(propsDir); - + public override void Save(string map) { if (cfg == null) cfg = ConfigElement.GetAll(typeof(TWMapConfig)); - ConfigElement.SerialiseSimple(cfg, Path(map), this); + SaveTo(cfg, propsDir, map); } - public void SetDefaults(Level lvl) { + public override void SetDefaults(Level lvl) { ushort midX = (ushort)(lvl.Width / 2); ushort midY = (ushort)(lvl.Height / 2 + 1); ushort maxZ = (ushort)(lvl.Length - 1);