Unify various round game map config classes under one class, and hence eliminate some code duplicaion

This commit is contained in:
UnknownShadow200 2019-08-03 17:30:13 +10:00
parent cac52c9179
commit ef830df75e
11 changed files with 110 additions and 109 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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();

View File

@ -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");

View File

@ -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")) {

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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) {
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);

View File

@ -30,12 +30,19 @@ namespace MCGalaxy.Games {
public string LastMap = "";
public LevelPicker Picker;
/// <summary> Messages general info about current round and players. </summary>
/// <remarks> e.g. who is alive, points of each team, etc. </remarks>
public abstract void OutputStatus(Player p);
/// <summary> The instance of this game's overall configuration object. </summary>
public abstract RoundsGameConfig GetConfig();
/// <summary> Updates state from the map specific configuration file. </summary>
public abstract void UpdateMapConfig();
/// <summary> Runs a single round of this game. </summary>
protected abstract void DoRound();
/// <summary> Gets the list of all players in this game. </summary>
protected abstract List<Player> GetPlayers();
/// <summary> Saves stats to the database for the given player. </summary>
protected virtual void SaveStats(Player pl) { }
protected abstract void StartGame();
@ -69,6 +76,7 @@ namespace MCGalaxy.Games {
t.Start();
}
/// <summary> Attempts to auto start this game with infinite rounds. </summary>
public void AutoStart() {
if (!GetConfig().StartImmediately) return;
try {

View File

@ -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 {
/// <summary> Stores map-specific game configuration state. </summary>
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);
}
/// <summary> Saves this configuration to disc. </summary>
public abstract void Save(string map);
/// <summary> Loads this configuration from disc. </summary>
public abstract void Load(string map);
/// <summary> Applies default values for config fields which differ per map. </summary>
/// <remarks> e.g. spawn positions, zones </remarks>
public abstract void SetDefaults(Level lvl);
}
/// <summary> Stores overall game configuration state. </summary>
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<string> Maps = new List<string>();
/// <summary> Whether users are allowed to auto-join maps used by this game. </summary>
/// <remarks> If false, users can only join these maps when manually /load ed. </remarks>
public abstract bool AllowAutoload { get; }
protected abstract string PropsPath { get; }
protected abstract string GameName { get; }

View File

@ -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) {
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);