diff --git a/MCGalaxy/Bots/BotsFile.cs b/MCGalaxy/Bots/BotsFile.cs
index 993e0b725..d8e1e6203 100644
--- a/MCGalaxy/Bots/BotsFile.cs
+++ b/MCGalaxy/Bots/BotsFile.cs
@@ -16,58 +16,59 @@
permissions and limitations under the Licenses.
*/
using System;
-using System.Collections.Generic;
using System.IO;
-using Newtonsoft.Json;
using MCGalaxy.Maths;
+using Newtonsoft.Json;
namespace MCGalaxy.Bots {
/// Maintains persistent data for in-game bots.
public static class BotsFile {
-
- public static List SavedBots = new List();
-
- static readonly object locker = new object();
-
- public static void Load() {
- if (!File.Exists(Paths.BotsFile)) return;
- lock (locker) {
- string json = File.ReadAllText(Paths.BotsFile);
- BotProperties[] bots = JsonConvert.DeserializeObject(json);
- SavedBots = new List(bots);
-
- foreach (BotProperties bot in SavedBots) {
- if (String.IsNullOrEmpty(bot.DisplayName))
- bot.DisplayName = bot.Name;
+
+ public static string BotsPath(string mapName) {
+ return "extra/bots/" + mapName + ".json";
+ }
+
+ public static void Load(Level lvl) {
+ string path = BotsPath(lvl.MapName);
+ if (!File.Exists(path)) return;
+ string json = File.ReadAllText(path);
+ BotProperties[] bots = JsonConvert.DeserializeObject(json);
+
+ foreach (BotProperties props in bots) {
+ if (String.IsNullOrEmpty(props.DisplayName)) {
+ props.DisplayName = props.Name;
}
+
+ PlayerBot bot = new PlayerBot(props.Name, lvl);
+ props.ApplyTo(bot);
+
+ bot.ModelBB = AABB.ModelAABB(bot.Model, lvl);
+ LoadAi(props, bot);
+ PlayerBot.Add(bot, false);
}
}
- static void Save() {
- BotProperties[] bots = SavedBots.ToArray();
- string json = JsonConvert.SerializeObject(bots);
+ public static void Save(Level lvl) {
+ PlayerBot[] bots = lvl.Bots.Items;
+ string path = BotsPath(lvl.MapName);
+ if (!File.Exists(path) && bots.Length == 0) return;
+
+ BotProperties[] props = new BotProperties[bots.Length];
+ for (int i = 0; i < props.Length; i++) {
+ BotProperties savedProps = new BotProperties();
+ savedProps.FromBot(bots[i]);
+ props[i] = savedProps;
+ }
+
+ string json = JsonConvert.SerializeObject(props);
try {
- File.WriteAllText(Paths.BotsFile, json);
+ File.WriteAllText(path, json);
} catch (Exception ex) {
Logger.Log(LogType.Warning, "Failed to save bots file");
Logger.LogError(ex);
}
}
-
- public static void LoadBots(Level lvl) {
- lock (locker) {
- foreach (BotProperties props in SavedBots) {
- if (lvl.name != props.Level) continue;
- PlayerBot bot = new PlayerBot(props.Name, lvl);
- props.ApplyTo(bot);
-
- bot.ModelBB = AABB.ModelAABB(bot.Model, lvl);
- LoadAi(props, bot);
- PlayerBot.Add(bot, false);
- }
- }
- }
static void LoadAi(BotProperties props, PlayerBot bot) {
if (String.IsNullOrEmpty(props.AI)) return;
@@ -78,96 +79,7 @@ namespace MCGalaxy.Bots {
}
bot.cur = props.CurInstruction;
- if (bot.cur >= bot.Instructions.Count)
- bot.cur = 0;
- }
-
- public static void UnloadBots(Level lvl) {
- lock (locker) {
- PlayerBot[] bots = lvl.Bots.Items;
-
- foreach (PlayerBot bot in bots) {
- DoUpdateBot(bot, false);
- }
- if (bots.Length > 0) Save();
- }
- }
-
- public static void RemoveBot(PlayerBot bot) {
- lock (locker) {
- for (int i = 0; i < SavedBots.Count; i++) {
- BotProperties props = SavedBots[i];
- if (bot.name != props.Name || bot.level.name != props.Level) continue;
- SavedBots.RemoveAt(i);
- Save();
- return;
- }
- }
- }
-
- /// Deletes all bots which are located on the given map.
- public static void DeleteBots(string level) {
- lock (locker) {
- int removed = 0;
- for (int i = 0; i < SavedBots.Count; i++) {
- BotProperties props = SavedBots[i];
- if (!props.Level.CaselessEq(level)) continue;
-
- SavedBots.RemoveAt(i);
- removed++; i--;
- }
- if (removed > 0) Save();
- }
- }
-
- /// Moves all bots located on the given source map to the destination map.
- public static void MoveBots(string srcLevel, string dstLevel) {
- lock (locker) {
- int moved = 0;
- for (int i = 0; i < SavedBots.Count; i++) {
- BotProperties props = SavedBots[i];
- if (!props.Level.CaselessEq(srcLevel)) continue;
-
- props.Level = dstLevel;
- moved++;
- }
- if (moved > 0) Save();
- }
- }
-
- /// Copies all bots located on the given source map to the destination map.
- public static void CopyBots(string srcLevel, string dstLevel) {
- lock (locker) {
- int copied = 0, count = SavedBots.Count;
- for (int i = 0; i < SavedBots.Count; i++) {
- BotProperties props = SavedBots[i];
- if (!props.Level.CaselessEq(srcLevel)) continue;
-
- BotProperties copy = props.Copy();
- copy.Level = dstLevel;
- SavedBots.Add(copy);
- copied++;
- }
- if (copied > 0) Save();
- }
- }
-
- public static void UpdateBot(PlayerBot bot) {
- lock (locker) DoUpdateBot(bot, true);
- }
-
- static void DoUpdateBot(PlayerBot bot, bool save) {
- foreach (BotProperties props in SavedBots) {
- if (bot.name != props.Name || bot.level.name != props.Level) continue;
- props.FromBot(bot);
- if (save) Save();
- return;
- }
-
- BotProperties newProps = new BotProperties();
- newProps.FromBot(bot);
- SavedBots.Add(newProps);
- if (save) Save();
+ if (bot.cur >= bot.Instructions.Count) bot.cur = 0;
}
}
@@ -208,7 +120,7 @@ namespace MCGalaxy.Bots {
}
public void ApplyTo(PlayerBot bot) {
- bot.Pos = new Position(X, Y, Z);
+ bot.Pos = new Position(X, Y, Z);
bot.SetYawPitch(RotX, RotY);
Orientation rot = bot.Rot;
rot.RotX = BodyX; rot.RotZ = BodyZ;
diff --git a/MCGalaxy/Bots/PlayerBot.cs b/MCGalaxy/Bots/PlayerBot.cs
index 4a1755ebe..17e1f4894 100644
--- a/MCGalaxy/Bots/PlayerBot.cs
+++ b/MCGalaxy/Bots/PlayerBot.cs
@@ -17,6 +17,7 @@
*/
using System;
using System.Collections.Generic;
+using System.IO;
using MCGalaxy.Bots;
using MCGalaxy.Maths;
using MCGalaxy.Network;
@@ -71,24 +72,24 @@ namespace MCGalaxy {
public static void Add(PlayerBot bot, bool save = true) {
bot.level.Bots.Add(bot);
bot.GlobalSpawn();
- if (save) BotsFile.UpdateBot(bot);
+ if (save) BotsFile.Save(bot.level);
}
public static void Remove(PlayerBot bot, bool save = true) {
bot.level.Bots.Remove(bot);
bot.GlobalDespawn();
bot.jumping = false;
- if (save) BotsFile.RemoveBot(bot);
+ if (save) BotsFile.Save(bot.level);
}
public static void UnloadFromLevel(Level lvl) {
- BotsFile.UnloadBots(lvl);
+ BotsFile.Save(lvl);
RemoveLoadedBots(lvl, false);
}
public static void RemoveAllFromLevel(Level lvl) {
- RemoveLoadedBots(lvl, true);
- BotsFile.DeleteBots(lvl.name);
+ RemoveLoadedBots(lvl, false);
+ BotsFile.Save(lvl);
}
static void RemoveLoadedBots(Level lvl, bool save) {
diff --git a/MCGalaxy/Commands/Bots/CmdBot.cs b/MCGalaxy/Commands/Bots/CmdBot.cs
index e54471f1c..0e99f3d86 100644
--- a/MCGalaxy/Commands/Bots/CmdBot.cs
+++ b/MCGalaxy/Commands/Bots/CmdBot.cs
@@ -102,7 +102,7 @@ namespace MCGalaxy.Commands.Bots {
Player.Message(p, "Set text shown when bot {0} %Sis clicked on to {1}", bot.ColoredName, text);
bot.ClickedOnText = text;
}
- BotsFile.UpdateBot(bot);
+ BotsFile.Save(bot.level);
}
public override void Help(Player p) {
diff --git a/MCGalaxy/Commands/Bots/CmdBotSet.cs b/MCGalaxy/Commands/Bots/CmdBotSet.cs
index b4915d325..6190c18de 100644
--- a/MCGalaxy/Commands/Bots/CmdBotSet.cs
+++ b/MCGalaxy/Commands/Bots/CmdBotSet.cs
@@ -74,7 +74,7 @@ namespace MCGalaxy.Commands.Bots {
static void UpdateBot(Player p, PlayerBot bot, string msg) {
Player.Message(p, bot.ColoredName + "%S" + msg);
Logger.Log(LogType.UserActivity, bot.name + msg);
- BotsFile.UpdateBot(bot);
+ BotsFile.Save(bot.level);
}
public override void Help(Player p) {
diff --git a/MCGalaxy/Commands/Bots/CmdBotSummon.cs b/MCGalaxy/Commands/Bots/CmdBotSummon.cs
index 2b530be93..a9c6300a2 100644
--- a/MCGalaxy/Commands/Bots/CmdBotSummon.cs
+++ b/MCGalaxy/Commands/Bots/CmdBotSummon.cs
@@ -36,7 +36,7 @@ namespace MCGalaxy.Commands.Bots {
if (bot == null) return;
bot.Pos = p.Pos; bot.SetYawPitch(p.Rot.RotY, p.Rot.HeadX);
- BotsFile.UpdateBot(bot);
+ BotsFile.Save(bot.level);
}
public override void Help(Player p) {
diff --git a/MCGalaxy/Commands/CPE/CmdEntityRot.cs b/MCGalaxy/Commands/CPE/CmdEntityRot.cs
index f46c756d2..f3e4c51ab 100644
--- a/MCGalaxy/Commands/CPE/CmdEntityRot.cs
+++ b/MCGalaxy/Commands/CPE/CmdEntityRot.cs
@@ -39,7 +39,7 @@ namespace MCGalaxy.Commands.CPE {
protected override void SetBotData(Player p, PlayerBot bot, string args) {
if (!ParseArgs(p, args, bot)) return;
- BotsFile.UpdateBot(bot);
+ BotsFile.Save(bot.level);
}
protected override void SetPlayerData(Player p, Player who, string args) {
diff --git a/MCGalaxy/Commands/CPE/CmdModel.cs b/MCGalaxy/Commands/CPE/CmdModel.cs
index 3772e650e..22232df0e 100644
--- a/MCGalaxy/Commands/CPE/CmdModel.cs
+++ b/MCGalaxy/Commands/CPE/CmdModel.cs
@@ -45,7 +45,7 @@ namespace MCGalaxy.Commands.CPE {
Entities.UpdateModel(bot, model);
Player.Message(p, "You changed the model of bot " + bot.ColoredName + " %Sto a &c" + model);
- BotsFile.UpdateBot(bot);
+ BotsFile.Save(bot.level);
}
protected override void SetPlayerData(Player p, Player who, string model) {
diff --git a/MCGalaxy/Commands/CPE/CmdSkin.cs b/MCGalaxy/Commands/CPE/CmdSkin.cs
index 312635bdb..48a25d391 100644
--- a/MCGalaxy/Commands/CPE/CmdSkin.cs
+++ b/MCGalaxy/Commands/CPE/CmdSkin.cs
@@ -43,7 +43,7 @@ namespace MCGalaxy.Commands.CPE {
bot.GlobalDespawn();
bot.GlobalSpawn();
- BotsFile.UpdateBot(bot);
+ BotsFile.Save(bot.level);
}
protected override void SetPlayerData(Player p, Player who, string skin) {
diff --git a/MCGalaxy/Commands/Chat/CmdColor.cs b/MCGalaxy/Commands/Chat/CmdColor.cs
index 35077e0fe..8256ef6c4 100644
--- a/MCGalaxy/Commands/Chat/CmdColor.cs
+++ b/MCGalaxy/Commands/Chat/CmdColor.cs
@@ -47,7 +47,7 @@ namespace MCGalaxy.Commands.Chatting {
bot.GlobalDespawn();
bot.GlobalSpawn();
- BotsFile.UpdateBot(bot);
+ BotsFile.Save(bot.level);
}
protected override void SetPlayerData(Player p, Player who, string colName) {
diff --git a/MCGalaxy/Commands/Chat/CmdNick.cs b/MCGalaxy/Commands/Chat/CmdNick.cs
index eeb17a831..5229a5f60 100644
--- a/MCGalaxy/Commands/Chat/CmdNick.cs
+++ b/MCGalaxy/Commands/Chat/CmdNick.cs
@@ -53,7 +53,7 @@ namespace MCGalaxy.Commands.Chatting {
bot.GlobalDespawn();
bot.GlobalSpawn();
- BotsFile.UpdateBot(bot);
+ BotsFile.Save(bot.level);
}
protected override void SetPlayerData(Player p, Player who, string nick) {
diff --git a/MCGalaxy/Levels/Level.cs b/MCGalaxy/Levels/Level.cs
index 3aa426c8e..37311d298 100644
--- a/MCGalaxy/Levels/Level.cs
+++ b/MCGalaxy/Levels/Level.cs
@@ -337,7 +337,7 @@ namespace MCGalaxy {
lvl.Config.jailroty = lvl.roty;
LoadMetadata(lvl);
- MCGalaxy.Bots.BotsFile.LoadBots(lvl);
+ MCGalaxy.Bots.BotsFile.Load(lvl);
object locker = ThreadSafeCache.DBCache.GetLocker(name);
lock (locker) {
diff --git a/MCGalaxy/Levels/LevelActions.cs b/MCGalaxy/Levels/LevelActions.cs
index 6c3ad645c..b2c1bab43 100644
--- a/MCGalaxy/Levels/LevelActions.cs
+++ b/MCGalaxy/Levels/LevelActions.cs
@@ -41,13 +41,14 @@ namespace MCGalaxy {
"blockdefs/lvl_" + dst + ".json");
MoveIfExists("blockprops/lvl_" + src + ".txt",
"blockprops/lvl_" + dst + ".txt");
+ MoveIfExists(BotsFile.BotsPath(src),
+ BotsFile.BotsPath(dst));
try {
MoveBackups(src, dst);
} catch {
}
- BotsFile.MoveBots(src, dst);
RenameDatabaseTables(src, dst);
BlockDBFile.MoveBackingFile(src, dst);
}
@@ -132,8 +133,8 @@ namespace MCGalaxy {
DeleteIfExists("levels/level properties/" + name + ".properties");
DeleteIfExists("blockdefs/lvl_" + name + ".json");
DeleteIfExists("blockprops/lvl_" + name + ".txt");
+ DeleteIfExists(BotsFile.BotsPath(name));
- BotsFile.DeleteBots(name);
DeleteDatabaseTables(name);
BlockDBFile.DeleteBackingFile(name);
}
@@ -217,8 +218,9 @@ namespace MCGalaxy {
"blockdefs/lvl_" + dst + ".json");
CopyIfExists("blockprops/lvl_" + src + ".txt",
"blockprops/lvl_" + dst + ".txt");
+ CopyIfExists(BotsFile.BotsPath(src),
+ BotsFile.BotsPath(dst));
- BotsFile.CopyBots(src, dst);
CopyDatabaseTables(src, dst);
}
diff --git a/MCGalaxy/Server/Server.cs b/MCGalaxy/Server/Server.cs
index cfd009251..975a698fe 100644
--- a/MCGalaxy/Server/Server.cs
+++ b/MCGalaxy/Server/Server.cs
@@ -128,6 +128,7 @@ namespace MCGalaxy {
Background.QueueOnce(UpgradeTasks.UpgradeDBTimeSpent);
Background.QueueOnce(LoadPlayerLists);
Background.QueueOnce(UpgradeTasks.UpgradeOldLockdown);
+ Background.QueueOnce(UpgradeTasks.UpgradeBots);
Background.QueueOnce(SetupSocket);
Background.QueueOnce(InitTimers);
@@ -163,6 +164,7 @@ namespace MCGalaxy {
if (!Directory.Exists("extra")) Directory.CreateDirectory("extra");
if (!Directory.Exists("extra/Waypoints")) Directory.CreateDirectory("extra/Waypoints");
+ if (!Directory.Exists("extra/bots")) Directory.CreateDirectory("extra/bots");
if (!Directory.Exists("blockdefs")) Directory.CreateDirectory("blockdefs");
}
@@ -192,7 +194,6 @@ namespace MCGalaxy {
zombie.LoadInfectMessages();
Colors.LoadList();
Alias.Load();
- Bots.BotsFile.Load();
BlockDefinition.LoadGlobal();
ImagePalette.Load();
diff --git a/MCGalaxy/Server/Tasks/UpgradeTasks.cs b/MCGalaxy/Server/Tasks/UpgradeTasks.cs
index bc7328714..35f593119 100644
--- a/MCGalaxy/Server/Tasks/UpgradeTasks.cs
+++ b/MCGalaxy/Server/Tasks/UpgradeTasks.cs
@@ -15,18 +15,14 @@
or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses.
*/
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
-using System.Threading;
-using MCGalaxy.Commands.World;
-using MCGalaxy.Games;
-using MCGalaxy.Generator;
-using MCGalaxy.DB;
-using System.Data;
-using System.Data.Common;
-using MCGalaxy.SQL;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using MCGalaxy.Bots;
+using MCGalaxy.DB;
+using MCGalaxy.SQL;
+using Newtonsoft.Json;
namespace MCGalaxy.Tasks {
internal static class UpgradeTasks {
@@ -182,6 +178,39 @@ namespace MCGalaxy.Tasks {
File.WriteAllLines(Paths.TempRanksFile, lines);
}
+ internal static void UpgradeBots(SchedulerTask task) {
+ if (!File.Exists(Paths.BotsFile)) return;
+ string json = File.ReadAllText(Paths.BotsFile);
+ File.WriteAllText(Paths.BotsFile + ".bak", json);
+ Logger.Log(LogType.SystemActivity, "Making bots file per-level.. " +
+ "saved backup of global bots file to extra/bots.json.bak");
+
+ BotProperties[] bots = JsonConvert.DeserializeObject(json);
+ Dictionary> botsByLevel = new Dictionary>();
+
+ foreach (BotProperties bot in bots) {
+ List levelBots;
+ if (bot.Level == null || bot.Level.Length == 0) continue;
+
+ if (!botsByLevel.TryGetValue(bot.Level, out levelBots)) {
+ levelBots = new List();
+ botsByLevel[bot.Level] = levelBots;
+ }
+ levelBots.Add(bot);
+ }
+
+ foreach (var kvp in botsByLevel) {
+ json = JsonConvert.SerializeObject(kvp.Value);
+ File.WriteAllText(BotsFile.BotsPath(kvp.Key), json);
+ }
+
+ if (Server.mainLevel.Bots.Count == 0) {
+ BotsFile.Load(Server.mainLevel);
+ }
+ File.Delete(Paths.BotsFile);
+ }
+
+
internal static void UpgradeDBTimeSpent(SchedulerTask task) {
DataTable table = Database.Backend.GetRows(PlayerData.DBTable, "TimeSpent", "LIMIT 1");
if (table.Rows.Count == 0) return; // no players
diff --git a/MCGalaxy/util/IO/Paths.cs b/MCGalaxy/util/IO/Paths.cs
index bd0d0422e..eea448f7e 100644
--- a/MCGalaxy/util/IO/Paths.cs
+++ b/MCGalaxy/util/IO/Paths.cs
@@ -34,16 +34,14 @@ namespace MCGalaxy {
public const string AliasesFile = "text/aliases.txt";
public const string NewsFile = "text/news.txt";
public const string WelcomeFile = "text/welcome.txt";
- public const string JokerFile = "text/joker.txt";
-
+ public const string JokerFile = "text/joker.txt";
public const string BlockPermsFile = "properties/block.properties";
public const string CmdPermsFile = "properties/command.properties";
public const string CmdExtraPermsFile = "properties/ExtraCommandPermissions.properties";
public const string EconomyPropsFile = "properties/economy.properties";
public const string ServerPropsFile = "properties/server.properties";
- public const string RankPropsFile = "properties/ranks.properties";
-
+ public const string RankPropsFile = "properties/ranks.properties";
public const string BotsFile = "extra/bots.json";
}