From 0deb3b3dd32af7a43ea979612bcd52d522136bcc Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 26 Jan 2016 23:58:24 +1100 Subject: [PATCH] Warning - may still have bugs. Finished per-level BlockDefinitions implementation. --- Commands/Command.All.cs | 1 + Commands/Fun/CmdAka.cs | 2 +- Commands/Information/CmdWhoip.cs | 2 +- Commands/Moderation/CmdRenameLvl.cs | 5 +++++ Commands/Moderation/CmdReveal.cs | 2 +- Commands/World/CmdCopyLVL.cs | 3 ++- Commands/World/CmdDeleteLvl.cs | 4 ++++ Commands/World/CmdGoto.cs | 3 ++- Commands/World/CmdMuseum.cs | 3 ++- Commands/building/CustomBlockCommand.cs | 26 ++++++++++++++++--------- Levels/BlockDefinitions.cs | 20 ++++++++++++++----- Levels/Level.cs | 8 +++++++- Network/Player.Networking.cs | 23 +++++++++++++++++----- Player/Player.cs | 5 +++-- 14 files changed, 79 insertions(+), 28 deletions(-) diff --git a/Commands/Command.All.cs b/Commands/Command.All.cs index ae8b64f50..f20c7b53d 100644 --- a/Commands/Command.All.cs +++ b/Commands/Command.All.cs @@ -149,6 +149,7 @@ namespace MCGalaxy all.Add(new CmdLoginMessage()); all.Add(new CmdLogoutMessage()); all.Add(new CmdLowlag()); + all.Add(new CmdLevelBlock()); all.Add(new CmdMain()); all.Add(new CmdMap()); all.Add(new CmdMapInfo()); diff --git a/Commands/Fun/CmdAka.cs b/Commands/Fun/CmdAka.cs index 9db2ab6de..9deb0c985 100644 --- a/Commands/Fun/CmdAka.cs +++ b/Commands/Fun/CmdAka.cs @@ -41,7 +41,7 @@ namespace MCGalaxy.Commands Player.GlobalDespawn(p, true); p.SendUserMOTD(); - p.SendMap(); + p.SendMap(p.level); if (!p.hidden) { Player.GlobalDespawn(p, false); diff --git a/Commands/Information/CmdWhoip.cs b/Commands/Information/CmdWhoip.cs index 5a83f18bb..078cd7a16 100644 --- a/Commands/Information/CmdWhoip.cs +++ b/Commands/Information/CmdWhoip.cs @@ -48,8 +48,8 @@ namespace MCGalaxy.Commands Player.SendMessage(p, playerNames); playerDb.Dispose(); - System.Math.Sign(System.Convert.ToInt32(0)); } + public override void Help(Player p) { p.SendMessage("/whoip - Displays players associated with a given IP address."); diff --git a/Commands/Moderation/CmdRenameLvl.cs b/Commands/Moderation/CmdRenameLvl.cs index a46fe1cc5..64d4361f6 100644 --- a/Commands/Moderation/CmdRenameLvl.cs +++ b/Commands/Moderation/CmdRenameLvl.cs @@ -61,6 +61,11 @@ namespace MCGalaxy.Commands File.Move("levels/level properties/" + foundLevel.name, "levels/level properties/" + newName + ".properties"); } catch { } + + try { + if (File.Exists("blockdefs/lvl_" + foundLevel.name + ".json")) + File.Move("blockdefs/lvl_" + foundLevel.name + ".json", "blockdefs/lvl_" + newName + ".json"); + } catch {} //Move and rename backups try diff --git a/Commands/Moderation/CmdReveal.cs b/Commands/Moderation/CmdReveal.cs index 9058e06c7..b9a9c8cba 100644 --- a/Commands/Moderation/CmdReveal.cs +++ b/Commands/Moderation/CmdReveal.cs @@ -72,7 +72,7 @@ namespace MCGalaxy.Commands { ushort x = who.pos[0], y = who.pos[1], z = who.pos[2]; Player.GlobalDespawn(who, true); - who.SendUserMOTD(); who.SendMap(); + who.SendUserMOTD(); who.SendMap(who.level); if (!who.hidden) Player.GlobalSpawn(who, x, y, z, who.level.rotx, who.level.roty, true); diff --git a/Commands/World/CmdCopyLVL.cs b/Commands/World/CmdCopyLVL.cs index 605f44f53..1c3590862 100644 --- a/Commands/World/CmdCopyLVL.cs +++ b/Commands/World/CmdCopyLVL.cs @@ -60,7 +60,8 @@ namespace MCGalaxy.Commands try { File.Copy("levels/" + msg1 + ".lvl", "levels/" + msg2 + ".lvl"); File.Copy("levels/level properties/" + msg1 + ".properties", "levels/level properties/" + msg1 + ".properties", false); - + if (File.Exists("blockdefs/lvl_" + msg1 + ".json")) + File.Copy("blockdefs/lvl_" + msg1 + ".json", "blockdefs/lvl_" + msg2 + ".json"); } catch (System.IO.FileNotFoundException) { Player.SendMessage(p, msg2 + " does not exist!"); return; diff --git a/Commands/World/CmdDeleteLvl.cs b/Commands/World/CmdDeleteLvl.cs index f6ca0d676..8e0a3f050 100644 --- a/Commands/World/CmdDeleteLvl.cs +++ b/Commands/World/CmdDeleteLvl.cs @@ -71,6 +71,10 @@ namespace MCGalaxy.Commands { try { File.Delete("levels/level properties/" + message + ".properties"); } catch { } try { File.Delete("levels/level properties/" + message); } catch { } + try { + if (File.Exists("blockdefs/lvl_" + message + ".json")) + File.Delete("blockdefs/lvl_" + message + ".json"); + } catch {} //safe against SQL injections because the levelname (message) is first being checked if it exists Database.executeQuery("DROP TABLE `Block" + message + "`"); diff --git a/Commands/World/CmdGoto.cs b/Commands/World/CmdGoto.cs index 78740ad49..0ac0cacc6 100644 --- a/Commands/World/CmdGoto.cs +++ b/Commands/World/CmdGoto.cs @@ -58,7 +58,8 @@ namespace MCGalaxy.Commands foreach (PlayerBot b in PlayerBot.playerbots) if (p.level == b.level) p.SendDespawn(b.id); Player.GlobalDespawn(p, true); - p.level = foundLevel; p.SendUserMOTD(); p.SendMap(); + Level oldLevel = p.level; + p.level = foundLevel; p.SendUserMOTD(); p.SendMap(oldLevel); GC.Collect(); diff --git a/Commands/World/CmdMuseum.cs b/Commands/World/CmdMuseum.cs index be124864f..d51d267cf 100644 --- a/Commands/World/CmdMuseum.cs +++ b/Commands/World/CmdMuseum.cs @@ -63,9 +63,10 @@ namespace MCGalaxy.Commands Player.GlobalDespawn(p, true); + Level oldLevel = p.level; p.level = level; p.SendMotd(); - if (!p.SendRawMap(level)) + if (!p.SendRawMap(oldLevel, level)) return; ushort x = (ushort)((0.5 + level.spawnx) * 32); diff --git a/Commands/building/CustomBlockCommand.cs b/Commands/building/CustomBlockCommand.cs index ccda1ef39..97437653b 100644 --- a/Commands/building/CustomBlockCommand.cs +++ b/Commands/building/CustomBlockCommand.cs @@ -66,9 +66,10 @@ namespace MCGalaxy.Commands { int targetId; if (parts.Length >= 2 ) { string id = parts[1]; - if (!CheckBlockId(p, id, out targetId)) return; + if (!CheckBlockId(p, id, global, out targetId)) return; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition def = defs[targetId]; + if (!global && def == BlockDefinition.GlobalDefs[targetId]) def = null; if (def != null) { Player.SendMessage(p, "There is already a custom block with the id " + id + @@ -100,10 +101,10 @@ namespace MCGalaxy.Commands { if (parts.Length > 1) int.TryParse(parts[1], out offset); BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; string cmd = global ? "/gb" : "/lb"; - for( int i = 1; i < 256; i++ ) { BlockDefinition def = defs[i]; - if (def == null) continue; + if (def == null) continue; + if (!global && def == BlockDefinition.GlobalDefs[i]) continue; if (index >= offset) { count++; @@ -122,15 +123,16 @@ namespace MCGalaxy.Commands { void RemoveHandler(Player p, string[] parts, bool global) { if (parts.Length <= 1) { Help(p); return; } - int blockID; - if (!CheckBlockId(p, parts[1], out blockID)) return; + int blockId; + if (!CheckBlockId(p, parts[1], global, out blockId)) return; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; - BlockDefinition def = defs[blockID]; + BlockDefinition def = defs[blockId]; + if (!global && def == BlockDefinition.GlobalDefs[blockId]) def = null; if (def == null) { MessageNoBlock(p, global); return; } BlockDefinition.Remove(def, defs, p == null ? null : p.level); - BlockDefinition globalDef = BlockDefinition.GlobalDefs[blockID]; + BlockDefinition globalDef = BlockDefinition.GlobalDefs[blockId]; if (!global && globalDef != null) { BlockDefinition.Add(globalDef, defs, p == null ? null : p.level); } @@ -215,6 +217,7 @@ namespace MCGalaxy.Commands { bd.FallBack = Block.Byte(value); BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition def = defs[bd.BlockID]; + if (!global && def == BlockDefinition.GlobalDefs[bd.BlockID]) def = null; // in case the list is modified before we finish the command. if (def != null) { @@ -223,6 +226,8 @@ namespace MCGalaxy.Commands { string cmd = global ? "/gb" : "/lb"; Player.SendMessage(p, "There are no custom block ids left, " + "you must " + cmd + " remove a custom block first."); + if (!global) + Player.SendMessage(p, "You may also manually specify the same existing id of a global custom block."); return; } } @@ -248,7 +253,7 @@ namespace MCGalaxy.Commands { return; } int blockId; - if (!CheckBlockId(p, parts[1], out blockId)) return; + if (!CheckBlockId(p, parts[1], global, out blockId)) return; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition def = defs[blockId]; if (def == null) { MessageNoBlock(p, global); return; } @@ -454,13 +459,16 @@ namespace MCGalaxy.Commands { Player.SendMessage(p, help[i].Replace("Type", "Use")); } - static bool CheckBlockId(Player p, string arg, out int blockId) { + static bool CheckBlockId(Player p, string arg, bool global, out int blockId) { if (!int.TryParse(arg, out blockId)) { Player.SendMessage(p, "Provided block id is not a number."); return false; } if (blockId <= 0 || blockId >= 255) { Player.SendMessage(p, "Block id must be between 1-254"); return false; } + if (!global && blockId < Block.CpeCount) { + Player.SendMessage(p, "You can only redefine standard blocks with /gb."); return false; + } return true; } diff --git a/Levels/BlockDefinitions.cs b/Levels/BlockDefinitions.cs index 60d6d2629..d560c9be3 100644 --- a/Levels/BlockDefinitions.cs +++ b/Levels/BlockDefinitions.cs @@ -60,12 +60,12 @@ namespace MCGalaxy { Save(true, null); } - static BlockDefinition[] Load(bool global, Level lvl) { + internal static BlockDefinition[] Load(bool global, Level lvl) { BlockDefinition[] defs = new BlockDefinition[256]; - string path = global ? GlobalPath : "blockdefs/" + lvl.name; + string path = global ? GlobalPath : "blockdefs/lvl_" + lvl.name + ".json"; try { - if (File.Exists(GlobalPath)) { - string json = File.ReadAllText(GlobalPath); + if (File.Exists(path)) { + string json = File.ReadAllText(path); defs = JsonConvert.DeserializeObject(json); } } catch (Exception ex) { @@ -82,8 +82,16 @@ namespace MCGalaxy { static void Save(bool global, Level lvl) { BlockDefinition[] defs = global ? GlobalDefs : lvl.CustomBlockDefs; + // We don't want to save global blocks in the level's custom blocks list + if (!global) { + BlockDefinition[] realDefs = new BlockDefinition[256]; + for (int i = 0; i < 256; i++) + realDefs[i] = defs[i] == GlobalDefs[i] ? null : defs[i]; + defs = realDefs; + } + string json = JsonConvert.SerializeObject(defs); - string path = global ? GlobalPath : "blockdefs/" + lvl.name; + string path = global ? GlobalPath : "blockdefs/lvl_" + lvl.name + ".json"; File.WriteAllText(path, json); } @@ -127,6 +135,8 @@ namespace MCGalaxy { foreach (Player pl in Player.players) { if (!global && pl.level != level) continue; + if (global && pl.level.CustomBlockDefs[id] != null) continue; + if (pl.HasCpeExt(CpeExt.BlockDefinitions)) pl.SendRaw(Opcode.CpeRemoveBlockDefinition, id); } diff --git a/Levels/Level.cs b/Levels/Level.cs index 488919590..e243d9186 100644 --- a/Levels/Level.cs +++ b/Levels/Level.cs @@ -554,7 +554,7 @@ namespace MCGalaxy { try { - Level level = LvlFile.Load(givenName,path); + Level level = LvlFile.Load(givenName, path); level.permissionbuild = LevelPermission.Builder; level.setPhysics(phys); //level.textures = new LevelTextures(level); @@ -631,6 +631,12 @@ namespace MCGalaxy } catch (Exception e) { Server.ErrorLog(e); } + + BlockDefinition[] defs = BlockDefinition.Load(false, level); + for (int i = 0; i < defs.Length; i++) { + if (defs[i] == null) continue; + level.CustomBlockDefs[i] = defs[i]; + } Server.s.Log(string.Format("Level \"{0}\" loaded.", level.name)); if (LevelLoaded != null) diff --git a/Network/Player.Networking.cs b/Network/Player.Networking.cs index 1214abaf7..61a8b3ab0 100644 --- a/Network/Player.Networking.cs +++ b/Network/Player.Networking.cs @@ -292,9 +292,9 @@ namespace MCGalaxy { SendRaw(Opcode.Handshake, buffer); } - public void SendMap() { SendRawMap(level); } + public void SendMap(Level oldLevel) { SendRawMap(oldLevel, level); } - public bool SendRawMap(Level level) { + public bool SendRawMap(Level oldLevel, Level level) { if ( level.blocks == null ) return false; bool success = true; bool hasBlockDefinitions = HasCpeExt(CpeExt.BlockDefinitions); @@ -361,8 +361,12 @@ namespace MCGalaxy { SendCurrentEnvColors(); if (HasCpeExt(CpeExt.EnvMapAppearance) || HasCpeExt(CpeExt.EnvMapAppearance, 2)) SendCurrentMapAppearance(); - if (HasCpeExt(CpeExt.BlockDefinitions)) - BlockDefinition.SendLevelCustomBlocks(this); + if (HasCpeExt(CpeExt.BlockDefinitions)) { + if (oldLevel != null && oldLevel != level) + RemoveOldLevelCustomBlocks(oldLevel); + BlockDefinition.SendLevelCustomBlocks(this); + } + if ( OnSendMap != null ) OnSendMap(this, buffer); if (!level.guns) @@ -380,7 +384,16 @@ namespace MCGalaxy { if (HasCpeExt(CpeExt.BlockPermissions)) SendCurrentBlockPermissions(); return success; - } + } + + void RemoveOldLevelCustomBlocks(Level oldLevel) { + BlockDefinition[] defs = oldLevel.CustomBlockDefs; + for (int i = Block.CpeCount; i < 256; i++) { + BlockDefinition def = defs[i]; + if (def == null || def == BlockDefinition.GlobalDefs[i]) continue; + SendRaw(Opcode.CpeRemoveBlockDefinition, (byte)i); + } + } public void SendSpawn(byte id, string name, ushort x, ushort y, ushort z, byte rotx, byte roty) { byte[] buffer = new byte[74]; diff --git a/Player/Player.cs b/Player/Player.cs index 87edd6396..8f3baf114 100644 --- a/Player/Player.cs +++ b/Player/Player.cs @@ -765,7 +765,7 @@ namespace MCGalaxy { void CompleteLoginProcess() { try { SendMotd(); - SendMap(); + SendMap(null); if (disconnected) return; loggedIn = true; @@ -1057,7 +1057,8 @@ namespace MCGalaxy { if (type >= Block.CpeCount) { if (!HasCpeExt(CpeExt.BlockDefinitions) || level.CustomBlockDefs[type] == null) { - SendMessage("Invalid block type: " + type); return; + SendMessage("Invalid block type: " + type); + RevertBlock(x, y, z); return; } extType = type; type = Block.custom_block;