Simplify /texture, /os map texture, and /botai

This commit is contained in:
UnknownShadow200 2018-04-04 11:37:48 +10:00
parent c7a57a39b0
commit dc70196f85
9 changed files with 173 additions and 171 deletions

View File

@ -49,7 +49,7 @@ namespace MCGalaxy.Bots {
} }
public override void Output(Player p, string[] args, StreamWriter w) { public override void Output(Player p, string[] args, StreamWriter w) {
string time = args.Length > 3 ? args[3] : "10"; string time = args.Length > 3 ? args[3] : "10";
string speed = args.Length > 4 ? args[4] : "2"; string speed = args.Length > 4 ? args[4] : "2";
w.WriteLine(Name + " " + short.Parse(time) + " " + byte.Parse(speed)); w.WriteLine(Name + " " + short.Parse(time) + " " + byte.Parse(speed));
} }

View File

@ -23,13 +23,13 @@ namespace MCGalaxy.Bots {
public static class ScriptFile { public static class ScriptFile {
public static bool Parse(Player p, PlayerBot bot, string file) { public static bool Parse(Player p, PlayerBot bot, string file) {
if (!File.Exists(file)) { if (!File.Exists(file)) {
Player.Message(p, "Could not find specified AI."); return false; Player.Message(p, "Could not find specified AI."); return false;
} }
string[] instructions = File.ReadAllLines(file); string[] instructions = File.ReadAllLines(file);
if (instructions.Length == 0 || !instructions[0].CaselessEq("#Version 2")) { if (instructions.Length == 0) {
Player.Message(p, "Invalid file version. Remake"); return false; Player.Message(p, "No instructions in the AI."); return false;
} }
bot.Instructions.Clear(); bot.Instructions.Clear();
@ -53,22 +53,29 @@ namespace MCGalaxy.Bots {
return true; return true;
} }
public static void Append(Player p, string ai, string action, string[] args) { public static string Append(Player p, string ai, string action, string[] args) {
using (StreamWriter w = new StreamWriter("bots/" + ai, true)) { using (StreamWriter w = new StreamWriter("bots/" + ai, true)) {
if (action.Length == 0) action = "walk"; if (action.Length == 0) action = "walk";
if (action.CaselessEq("tp")) action = "teleport"; if (action.CaselessEq("tp")) action = "teleport";
BotInstruction ins = BotInstruction.Find(action); BotInstruction ins = BotInstruction.Find(action);
if (ins == null) { if (ins == null) {
Player.Message(p, "Could not find instruction \"" + action + "\""); return; Player.Message(p, "Could not find instruction \"" + action + "\""); return null;
} }
LevelPermission killPerm = CommandExtraPerms.MinPerm("botset"); LevelPermission killPerm = CommandExtraPerms.MinPerm("botset");
if (ins.Name.CaselessEq("kill") && p.Rank < killPerm) { if (ins.Name.CaselessEq("kill") && p.Rank < killPerm) {
Formatter.MessageNeedMinPerm(p, "+ can toggle a bot's killer instinct.", killPerm); Formatter.MessageNeedMinPerm(p, "+ can toggle a bot's killer instinct.", killPerm);
return; return null;
} }
ins.Output(p, args, w);
try {
ins.Output(p, args, w);
} catch {
Player.Message(p, "Invalid arguments given for instruction " + ins.Name);
return null;
}
return ins.Name;
} }
} }
} }

View File

@ -31,7 +31,8 @@ namespace MCGalaxy.Commands.Bots{
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
string[] args = message.SplitSpaces(); string[] args = message.SplitSpaces();
if (args[0].CaselessEq("list")) { string cmd = args[0];
if (cmd.CaselessEq("list")) {
string modifier = args.Length > 1 ? args[1] : ""; string modifier = args.Length > 1 ? args[1] : "";
HandleList(p, modifier); HandleList(p, modifier);
return; return;
@ -43,11 +44,14 @@ namespace MCGalaxy.Commands.Bots{
if (!Formatter.ValidName(p, ai, "bot AI")) return; if (!Formatter.ValidName(p, ai, "bot AI")) return;
if (ai == "hunt" || ai == "kill") { Player.Message(p, "Reserved for special AI."); return; } if (ai == "hunt" || ai == "kill") { Player.Message(p, "Reserved for special AI."); return; }
switch (args[0].ToLower()) { if (cmd.CaselessEq("add")) {
case "add": HandleAdd(p, ai, args); break; HandleAdd(p, ai, args);
case "del": HandleDelete(p, ai, args); break; } else if (cmd.CaselessEq("del")) {
case "info": HandleInfo(p, ai); break; HandleDelete(p, ai, args);
default: Help(p); break; } else if (cmd.CaselessEq("info")) {
HandleInfo(p, ai);
} else {
Help(p);
} }
} }
@ -55,7 +59,7 @@ namespace MCGalaxy.Commands.Bots{
if (!Directory.Exists("bots/deleted")) if (!Directory.Exists("bots/deleted"))
Directory.CreateDirectory("bots/deleted"); Directory.CreateDirectory("bots/deleted");
if (!File.Exists("bots/" + ai)) { if (!File.Exists("bots/" + ai)) {
Player.Message(p, "Could not find specified AI."); return; Player.Message(p, "Could not find specified bot AI."); return;
} }
for (int attempt = 0; attempt < 10; attempt++) { for (int attempt = 0; attempt < 10; attempt++) {
@ -78,7 +82,7 @@ namespace MCGalaxy.Commands.Bots{
} else { } else {
File.Move("bots/" + ai, "bots/deleted/" + ai + attempt); File.Move("bots/" + ai, "bots/deleted/" + ai + attempt);
} }
Player.Message(p, "Deleted &b" + ai); Player.Message(p, "Deleted bot AI &b" + ai);
} }
static void DeleteLast(Player p, string ai) { static void DeleteLast(Player p, string ai) {
@ -86,47 +90,39 @@ namespace MCGalaxy.Commands.Bots{
if (lines.Count > 0) lines.RemoveAt(lines.Count - 1); if (lines.Count > 0) lines.RemoveAt(lines.Count - 1);
File.WriteAllLines("bots/" + ai, lines.ToArray()); File.WriteAllLines("bots/" + ai, lines.ToArray());
Player.Message(p, "Deleted the last instruction from " + ai); Player.Message(p, "Deleted last instruction from bot AI &b" + ai);
} }
void HandleAdd(Player p, string ai, string[] args) { void HandleAdd(Player p, string ai, string[] args) {
string[] instructions; if (!File.Exists("bots/" + ai)) {
try { instructions = File.ReadAllLines("bots/" + ai); } Player.Message(p, "Created new bot AI: &b" + ai);
catch { instructions = new string[1]; } using (StreamWriter w = new StreamWriter("bots/" + ai)) {
// For backwards compatibility
try { w.WriteLine("#Version 2");
if (!File.Exists("bots/" + ai)) {
Player.Message(p, "Created new bot AI: &b" + ai);
using (StreamWriter w = new StreamWriter("bots/" + ai))
w.WriteLine("#Version 2");
} else if (!instructions[0].CaselessEq("#Version 2")) {
Player.Message(p, "File found is out-of-date. Overwriting");
File.Delete("bots/" + ai);
using (StreamWriter w = new StreamWriter("bots/" + ai))
w.WriteLine("#Version 2");
} else {
Player.Message(p, "Appended to bot AI: &b" + ai);
} }
} catch {
Player.Message(p, "An error occurred when accessing the files. You may need to delete it."); return;
} }
try { string action = args.Length > 2 ? args[2] : "";
string action = args.Length > 2 ? args[2] : ""; if (action.CaselessEq("reverse")) {
if (!action.CaselessEq("reverse")) { HandleReverse(p, ai);
ScriptFile.Append(p, ai, action, args); return; } else {
string instruction = ScriptFile.Append(p, ai, action, args);
if (instruction != null) {
Player.Message(p, "Appended " + instruction + " instruction to bot AI &b" + ai);
} }
}
using (StreamWriter w = new StreamWriter("bots/" + ai, true)) { }
for (int i = instructions.Length - 1; i > 0; i--) {
if (instructions[i].Length > 0 && instructions[i][0] != '#') { void HandleReverse(Player p, string ai) {
w.WriteLine(instructions[i]); string[] instructions = File.ReadAllLines("bots/" + ai);
} using (StreamWriter w = new StreamWriter("bots/" + ai, true)) {
for (int i = instructions.Length - 1; i > 0; i--) {
if (instructions[i].Length > 0 && instructions[i][0] != '#') {
w.WriteLine(instructions[i]);
} }
} }
} catch {
Player.Message(p, "Invalid parameter");
} }
Player.Message(p, "Appended all instructions in reverse order to bot AI &b" + ai);
} }
void HandleList(Player p, string modifier) { void HandleList(Player p, string modifier) {
@ -157,7 +153,7 @@ namespace MCGalaxy.Commands.Bots{
Player.Message(p, "%T/BotAI add [name] [instruction] <args>"); Player.Message(p, "%T/BotAI add [name] [instruction] <args>");
Player.Message(p, "%HInstructions: %S{0}, reverse", Player.Message(p, "%HInstructions: %S{0}, reverse",
BotInstruction.Instructions.Join(ins => ins.Name.ToLower())); BotInstruction.Instructions.Join(ins => ins.Name));
Player.Message(p, "%HTo see detailed help, type %T/Help BotAI [instruction]"); Player.Message(p, "%HTo see detailed help, type %T/Help BotAI [instruction]");
} }
@ -165,7 +161,7 @@ namespace MCGalaxy.Commands.Bots{
BotInstruction ins = BotInstruction.Find(message); BotInstruction ins = BotInstruction.Find(message);
if (ins == null) { if (ins == null) {
Player.Message(p, "%HInstructions: %S{0}, reverse", Player.Message(p, "%HInstructions: %S{0}, reverse",
BotInstruction.Instructions.Join(ins2 => ins2.Name.ToLower())); BotInstruction.Instructions.Join(ins2 => ins2.Name));
} else { } else {
Player.MessageLines(p, ins.Help); Player.MessageLines(p, ins.Help);
} }

View File

@ -17,111 +17,116 @@
*/ */
namespace MCGalaxy.Commands.CPE { namespace MCGalaxy.Commands.CPE {
public sealed class CmdTexture : Command { public sealed class CmdTexture : Command {
public override string name { get { return "Texture"; } } public override string name { get { return "Texture"; } }
public override string type { get { return CommandTypes.Other; } } public override string type { get { return CommandTypes.Other; } }
public override LevelPermission defaultRank { get { return LevelPermission.Operator; } } public override LevelPermission defaultRank { get { return LevelPermission.Operator; } }
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
if (message.Length == 0) { Help(p); return; } if (message.Length == 0) { Help(p); return; }
string[] args = message.SplitSpaces(); string[] args = message.SplitSpaces();
string scope = args[0].ToLower(); string scope = args[0].ToLower();
if (scope == "local") scope = "level"; if (scope == "local") scope = "level";
if (scope == "localzip") scope = "levelzip"; if (scope == "localzip") scope = "levelzip";
if (args.Length == 1) { if (args.Length == 1) {
if (scope == "level") if (scope == "level")
Player.Message(p, "Level terrain: " + GetPath(p.level.Config.Terrain)); Player.Message(p, "Level terrain: " + GetPath(p.level.Config.Terrain));
else if (scope == "levelzip") else if (scope == "levelzip")
Player.Message(p, "Level tex pack: " + GetPath(p.level.Config.TexturePack)); Player.Message(p, "Level tex pack: " + GetPath(p.level.Config.TexturePack));
else if (scope == "global") else if (scope == "global")
Player.Message(p, "Global terrain: " + GetPath(ServerConfig.DefaultTerrain)); Player.Message(p, "Global terrain: " + GetPath(ServerConfig.DefaultTerrain));
else if (scope == "globalzip") else if (scope == "globalzip")
Player.Message(p, "Global tex pack: " + GetPath(ServerConfig.DefaultTexture)); Player.Message(p, "Global tex pack: " + GetPath(ServerConfig.DefaultTexture));
else else
Help(p); Help(p);
return; return;
} }
string url = args[1]; string url = args[1];
if (url.CaselessEq("normal") || url.CaselessEq("reset")) { if (url.CaselessEq("normal") || url.CaselessEq("reset")) {
url = ""; url = "";
} else if (!(url.StartsWith("http://") || url.StartsWith("https://"))) { } else if (!(url.StartsWith("http://") || url.StartsWith("https://"))) {
Player.Message(p, "Please use http:// or https:// in front of your URL"); return; Player.Message(p, "Please use http:// or https:// in front of your URL"); return;
} }
FilterURL(ref url); FilterURL(ref url);
if ((scope == "global" || scope == "level") && !(url.Length == 0 || url.EndsWith(".png"))) { if (url.Length > NetUtils.StringSize) {
Player.Message(p, "The terrain URL must end in a .png"); return; Player.Message(p, "The URL must be " + NetUtils.StringSize + " characters or less."); return;
} }
if ((scope == "globalzip" || scope == "levelzip") && !(url.Length == 0 || url.EndsWith(".zip"))) { if (url.Length > 0 && !(url.EndsWith(".png") || url.EndsWith(".zip"))) {
Player.Message(p, "The texture pack URL must end in a .zip"); return; Player.Message(p, "URL must end in .png (for terrain) or .zip (for texture pack)"); return;
} }
if (url.Length > NetUtils.StringSize) {
Player.Message(p, "The URL must be " + NetUtils.StringSize + " characters or less."); return; if (scope == "global" || scope == "globalzip") {
} if (url.Length == 0) {
ServerConfig.DefaultTerrain = "";
string path = url.Length == 0 ? "normal" : url; ServerConfig.DefaultTexture = "";
if (scope == "global") { Player.Message(p, "Reset server textures to default");
ServerConfig.DefaultTerrain = url; } else if (url.CaselessEnds(".png")) {
Player.Message(p, "Set server's default terrain to " + path); ServerConfig.DefaultTerrain = url;
UpdateGlobally(p, false); Player.Message(p, "Set server's default terrain to " + url);
} else if (scope == "level") { } else if (url.CaselessEnds(".zip")) {
if (!LevelInfo.ValidateAction(p, p.level.name, "set texture of this level")) return; ServerConfig.DefaultTexture = url;
p.level.Config.Terrain = url; Player.Message(p, "Set server's default texture pack to " + url);
Player.Message(p, "Set level's terrain to " + path); }
UpdateLevel(p); UpdateGlobal(p);
} else if (scope == "globalzip") { } else if (scope == "level" || scope == "levelzip") {
ServerConfig.DefaultTexture = url; if (!LevelInfo.ValidateAction(p, p.level.name, "set texture of this level")) return;
Player.Message(p, "Set server's default texture pack to " + path);
UpdateGlobally(p, true); if (url.Length == 0) {
} else if (scope == "levelzip") { p.level.Config.Terrain = "";
if (!LevelInfo.ValidateAction(p, p.level.name, "set texture pack of this level")) return; p.level.Config.TexturePack = "";
p.level.Config.TexturePack = url; Player.Message(p, "Reset level textures to server default");
Player.Message(p, "Set level's texture pack to " + path); } else if (url.CaselessEnds(".png")) {
UpdateLevel(p); p.level.Config.Terrain = url;
} else { Player.Message(p, "Set level's default terrain to " + url);
Help(p); } else if (url.CaselessEnds(".zip")) {
} p.level.Config.TexturePack = url;
} Player.Message(p, "Set level's default texture pack to " + url);
}
internal static void FilterURL(ref string url) { UpdateLevel(p);
// a lot of people try linking to the dropbox page instead of directly to file, so we auto correct them } else {
if (url.StartsWith("http://www.dropbox")) { Help(p);
url = "http://dl.dropbox" + url.Substring("http://www.dropbox".Length); }
url = url.Replace("?dl=0", ""); }
} else if (url.StartsWith("https://www.dropbox")) {
url = "https://dl.dropbox" + url.Substring("https://www.dropbox".Length); internal static void FilterURL(ref string url) {
url = url.Replace("?dl=0", ""); // a lot of people try linking to the dropbox page instead of directly to file, so we auto correct them
} if (url.StartsWith("http://www.dropbox")) {
} url = "http://dl.dropbox" + url.Substring("http://www.dropbox".Length);
url = url.Replace("?dl=0", "");
static string GetPath(string url) { return url.Length == 0 ? "(none)" : url; } } else if (url.StartsWith("https://www.dropbox")) {
url = "https://dl.dropbox" + url.Substring("https://www.dropbox".Length);
void UpdateGlobally(Player p, bool zip) { url = url.Replace("?dl=0", "");
Player[] players = PlayerInfo.Online.Items; }
foreach (Player pl in players) { }
string url = zip ? pl.level.Config.TexturePack : pl.level.Config.Terrain;
if (url.Length == 0) pl.SendCurrentTextures(); static string GetPath(string url) { return url.Length == 0 ? "(none)" : url; }
}
SrvProperties.Save(); void UpdateGlobal(Player p) {
} Player[] players = PlayerInfo.Online.Items;
foreach (Player pl in players) {
void UpdateLevel(Player p) { pl.SendCurrentTextures();
Player[] players = PlayerInfo.Online.Items; }
foreach (Player pl in players) { SrvProperties.Save();
if (pl.level != p.level) continue; }
pl.SendCurrentTextures();
} void UpdateLevel(Player p) {
Level.SaveSettings(p.level); Player[] players = PlayerInfo.Online.Items;
} foreach (Player pl in players) {
if (pl.level != p.level) continue;
public override void Help(Player p) { pl.SendCurrentTextures();
Player.Message(p, "%T/Texture [scope] [url]"); }
Player.Message(p, "%H global/globalzip scope: Changes server's default texture."); Level.SaveSettings(p.level);
Player.Message(p, "%H level/levelzip scope: Changes current level's texture."); }
Player.Message(p, "%HUsing 'reset' as a url will reset the texture to default.");
Player.Message(p, "%HNote: zip texture packs are not supported by all clients."); public override void Help(Player p) {
} Player.Message(p, "%T/Texture global/level [url]");
} Player.Message(p, "%HChanges server default or current level's texture.");
Player.Message(p, "%H[url] must end with .png (terrain) or .zip (texture pack)");
Player.Message(p, "%HUsing 'reset' for [url] will reset the texture to default");
Player.Message(p, "%H Note: zip texture packs are not supported by all clients");
}
}
} }

View File

@ -157,9 +157,9 @@ namespace MCGalaxy.Commands.Info {
void ShowEnv(Player p, MapInfoData data, LevelConfig cfg) { void ShowEnv(Player p, MapInfoData data, LevelConfig cfg) {
string url = cfg.Terrain.Length > 0 ? cfg.Terrain : ServerConfig.DefaultTerrain; string url = cfg.Terrain.Length > 0 ? cfg.Terrain : ServerConfig.DefaultTerrain;
if (url.Length > 0) { if (url.Length > 0) {
Player.Message(p, "Texture: %b" + url); Player.Message(p, "Terrain: %b" + url);
} else { } else {
Player.Message(p, "No custom texture set for this map."); Player.Message(p, "No custom terrain set for this map.");
} }
url = cfg.TexturePack.Length > 0 ? cfg.TexturePack : ServerConfig.DefaultTexture; url = cfg.TexturePack.Length > 0 ? cfg.TexturePack : ServerConfig.DefaultTexture;

View File

@ -130,13 +130,7 @@ namespace MCGalaxy.Commands.World {
string rank = value.Length == 0 ? ServerConfig.DefaultRankName : value; string rank = value.Length == 0 ? ServerConfig.DefaultRankName : value;
Group grp = Matcher.FindRanks(p, rank); Group grp = Matcher.FindRanks(p, rank);
if (grp != null) p.level.BuildAccess.SetMin(null, grp); if (grp != null) p.level.BuildAccess.SetMin(null, grp);
} else if (cmd == "TEXTURE") { } else if (cmd == "TEXTURE" || cmd == "TEXTUREZIP" || cmd == "TEXTUREPACK") {
if (value.Length == 0) {
Command.all.FindByName("Texture").Use(p, "level normal");
} else {
Command.all.FindByName("Texture").Use(p, "level " + value);
}
} else if (cmd == "TEXTUREZIP" || cmd == "TEXTUREPACK") {
if (value.Length == 0) { if (value.Length == 0) {
Command.all.FindByName("Texture").Use(p, "levelzip normal"); Command.all.FindByName("Texture").Use(p, "levelzip normal");
} else { } else {

View File

@ -60,9 +60,9 @@ namespace MCGalaxy.DB {
BlockDBFile.ReadHeader(s, out Dims); BlockDBFile.ReadHeader(s, out Dims);
} }
/// <summary> Writes the entries from the in-memory cache to disc. </summary> /// <summary> Flushes the entries from the in-memory cache to disc. </summary>
/// <remarks> You must lock using Locker.AccquireWrite() **before** entering this method. </remarks> /// <remarks> You must lock using Locker.AccquireWrite() **before** entering this method. </remarks>
public void WriteEntries() { public void FlushCache() {
if (Cache.Head == null) return; if (Cache.Head == null) return;
BlockDBFile format = ValidateBackingFile(); BlockDBFile format = ValidateBackingFile();

View File

@ -224,7 +224,7 @@ namespace MCGalaxy.Drawing.Ops {
op.TotalModified++; op.TotalModified++;
// Attempt to prevent the BlockDB from growing too large (> 1,000,000 entries) // Attempt to prevent BlockDB in-memory cache from growing too large (> 1,000,000 entries)
int count = lvl.BlockDB.Cache.Count; int count = lvl.BlockDB.Cache.Count;
if (count == 0 || (count % 1000000) != 0) return; if (count == 0 || (count % 1000000) != 0) return;
@ -236,7 +236,7 @@ namespace MCGalaxy.Drawing.Ops {
} }
using (IDisposable wLock = lvl.BlockDB.Locker.AccquireWrite(100)) { using (IDisposable wLock = lvl.BlockDB.Locker.AccquireWrite(100)) {
if (wLock != null) lvl.BlockDB.WriteEntries(); if (wLock != null) lvl.BlockDB.FlushCache();
} }
if (!hasReadLock) return; if (!hasReadLock) return;

View File

@ -34,7 +34,7 @@ namespace MCGalaxy {
Logger.Log(LogType.Warning, "Couldn't accquire BlockDB write lock on {0}, skipping save", lvl.name); Logger.Log(LogType.Warning, "Couldn't accquire BlockDB write lock on {0}, skipping save", lvl.name);
return; return;
} }
lvl.BlockDB.WriteEntries(); lvl.BlockDB.FlushCache();
} }
Logger.Log(LogType.BackgroundActivity, "Saved BlockDB changes for: {0}", lvl.name); Logger.Log(LogType.BackgroundActivity, "Saved BlockDB changes for: {0}", lvl.name);
} }