diff --git a/GUI/PropertyWindow/PropertyWindow.Blocks.cs b/GUI/PropertyWindow/PropertyWindow.Blocks.cs
index 709f2fce1..463c33896 100644
--- a/GUI/PropertyWindow/PropertyWindow.Blocks.cs
+++ b/GUI/PropertyWindow/PropertyWindow.Blocks.cs
@@ -63,7 +63,7 @@ namespace MCGalaxy.Gui {
}
}
- BlockProps.Save("core", Block.Props);
+ BlockProps.Save("core", Block.Props, true);
BlockPerms.Save();
Block.SetBlocks();
LoadBlocks();
diff --git a/MCGalaxy/Blocks/BlockProperties.cs b/MCGalaxy/Blocks/BlockProperties.cs
index 97ba2b70c..04fe2c5c6 100644
--- a/MCGalaxy/Blocks/BlockProperties.cs
+++ b/MCGalaxy/Blocks/BlockProperties.cs
@@ -29,9 +29,6 @@ namespace MCGalaxy.Blocks {
/// Extended and physics properties of a block.
public struct BlockProps {
- /// ID of block these properties are associated with.
- public byte BlockId;
-
/// Standard block id sent to clients in map and block update packets.
public byte ConvertId;
@@ -74,14 +71,13 @@ namespace MCGalaxy.Blocks {
public BlockProps(byte block) {
this = default(BlockProps);
- BlockId = block;
ConvertId = block;
Name = "unknown";
ODoorId = Block.Invalid;
}
- public static void Save(string group, BlockProps[] scope) {
+ public static void Save(string group, BlockProps[] scope, bool custom) {
if (!Directory.Exists("blockprops"))
Directory.CreateDirectory("blockprops");
@@ -93,8 +89,13 @@ namespace MCGalaxy.Blocks {
if (!scope[i].Changed) continue;
BlockProps props = scope[i];
+ // Don't save physics blocks
+ if (custom && (i > Block.CpeCount && i < Block.Count)) continue;
+ // Convert ext to raw ids
+ int id = i >= Block.Count ? (i - 256) : i;
+
string deathMsg = props.DeathMessage == null ? "" : props.DeathMessage.Replace(":", "\\;");
- w.WriteLine(i + ":" + props.IsRails + ":" + props.IsTDoor + ":" + props.IsDoor + ":"
+ w.WriteLine(id + ":" + props.IsRails + ":" + props.IsTDoor + ":" + props.IsDoor + ":"
+ props.IsMessageBlock + ":" + props.IsPortal + ":" + props.WaterKills + ":"
+ props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg + ":"
+ (byte)props.AnimalAI);
diff --git a/MCGalaxy/Commands/CPE/CustomBlockCommand.cs b/MCGalaxy/Commands/CPE/CustomBlockCommand.cs
index f6fd3701e..fb9d19db4 100644
--- a/MCGalaxy/Commands/CPE/CustomBlockCommand.cs
+++ b/MCGalaxy/Commands/CPE/CustomBlockCommand.cs
@@ -117,7 +117,6 @@ namespace MCGalaxy.Commands.CPE {
BlockProps props = global ? BlockDefinition.GlobalProps[src.Index] : p.level.BlockProps[src.Index];
dstDef = srcDef.Copy();
- props.BlockId = (byte)dst.RawID;
dstDef.BlockID = (byte)dst.RawID;
AddBlock(p, dstDef, global, cmd, props);
@@ -454,10 +453,11 @@ namespace MCGalaxy.Commands.CPE {
BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
BlockDefinition old = defs[def.BlockID];
if (!global && old == BlockDefinition.GlobalDefs[def.BlockID]) old = null;
+ ExtBlock block;
// in case the list is modified before we finish the command.
if (old != null) {
- ExtBlock block = GetFreeBlock(global, p == null ? null : p.level);
+ block = GetFreeBlock(global, p == null ? null : p.level);
if (block.IsInvalid) {
Player.Message(p, "There are no custom block ids left, " +
"you must " + cmd + " remove a custom block first.");
@@ -471,7 +471,9 @@ namespace MCGalaxy.Commands.CPE {
string scope = global ? "global" : "level";
Player.Message(p, "Created a new " + scope + " custom block " + def.Name + "(" + def.BlockID + ")");
- UpdateBlockProps(global, p, props);
+
+ block = ExtBlock.FromRaw(def.BlockID);
+ UpdateBlockProps(global, p, block, props);
BlockDefinition.Add(def, defs, p == null ? null : p.level);
return true;
}
@@ -558,17 +560,17 @@ namespace MCGalaxy.Commands.CPE {
}
- static void UpdateBlockProps(bool global, Player p, BlockProps props) {
- ExtBlock block = ExtBlock.FromRaw(props.BlockId);
+ static void UpdateBlockProps(bool global, Player p, ExtBlock block, BlockProps props) {
if (!global) {
p.level.BlockProps[block.Index] = props;
return;
}
BlockDefinition.GlobalProps[block.Index] = props;
- Level[] loaded = LevelInfo.Loaded.Items;
+ Level[] loaded = LevelInfo.Loaded.Items;
+ byte raw = block.BlockID;
foreach (Level lvl in loaded) {
- if (lvl.CustomBlockDefs[props.BlockId] != null) continue;
+ if (lvl.CustomBlockDefs[raw] != null) continue;
lvl.BlockProps[block.Index] = props;
}
}
diff --git a/MCGalaxy/Commands/CommandParser.cs b/MCGalaxy/Commands/CommandParser.cs
index a60628cac..9b711544d 100644
--- a/MCGalaxy/Commands/CommandParser.cs
+++ b/MCGalaxy/Commands/CommandParser.cs
@@ -132,18 +132,21 @@ namespace MCGalaxy.Commands {
block = ExtBlock.Invalid; return true;
}
+ block = RawGetBlock(p, input);
+ return !block.IsInvalid;
+ }
+
+ /// Attempts to parse the given argument as either a block name or a block ID.
+ /// This does not output any messages to the player.
+ public static ExtBlock RawGetBlock(Player p, string input) {
+ ExtBlock block = default(ExtBlock);
block.BlockID = Block.Byte(input);
- if (block.BlockID != Block.Invalid) return true;
+ if (!block.IsInvalid) return block;
// find custom block
byte raw = BlockDefinition.GetBlock(input, p);
- if (raw == Block.Invalid) {
- Player.Message(p, "&cThere is no block \"{0}\".", input);
- return false;
- } else {
- block = ExtBlock.FromRaw(raw);
- return true;
- }
+ if (raw != Block.Invalid) return ExtBlock.FromRaw(raw);
+ return ExtBlock.Invalid;
}
/// Attempts to parse the given argument as either a block name or a block ID.
diff --git a/MCGalaxy/Commands/World/CmdBlockProperties.cs b/MCGalaxy/Commands/World/CmdBlockProperties.cs
index b865b2ca4..c4d5749e6 100644
--- a/MCGalaxy/Commands/World/CmdBlockProperties.cs
+++ b/MCGalaxy/Commands/World/CmdBlockProperties.cs
@@ -176,7 +176,7 @@ namespace MCGalaxy.Commands.World {
scope[block.Index].Changed = true;
if (scope == Block.Props) {
- BlockProps.Save("core", scope);
+ BlockProps.Save("core", scope, true);
Level[] loaded = LevelInfo.Loaded.Items;
foreach (Level lvl in loaded) {
@@ -185,7 +185,7 @@ namespace MCGalaxy.Commands.World {
}
} else if (scope == BlockDefinition.GlobalProps) {
Level[] loaded = LevelInfo.Loaded.Items;
- BlockProps.Save("global", scope);
+ BlockProps.Save("global", scope, false);
byte raw = block.RawID;
foreach (Level lvl in loaded) {
@@ -194,7 +194,7 @@ namespace MCGalaxy.Commands.World {
lvl.SetBlockHandler(block);
}
} else {
- BlockProps.Save("lvl_" + level.name, scope);
+ BlockProps.Save("lvl_" + level.name, scope, false);
level.SetBlockHandler(block);
}
}
diff --git a/MCGalaxy/Commands/building/CmdMessageBlock.cs b/MCGalaxy/Commands/building/CmdMessageBlock.cs
index 4fa6af7dd..7f89b337b 100644
--- a/MCGalaxy/Commands/building/CmdMessageBlock.cs
+++ b/MCGalaxy/Commands/building/CmdMessageBlock.cs
@@ -65,25 +65,23 @@ namespace MCGalaxy.Commands.Building {
}
ExtBlock GetBlock(Player p, string name, ref bool allMessage) {
- byte block = Block.Byte(name);
- if (Block.Props[block].IsMessageBlock) return (ExtBlock)block;
if (name == "show") { ShowMessageBlocks(p); return ExtBlock.Invalid; }
-
- block = BlockDefinition.GetBlock(name, p);
- if (p.level.BlockProps[block].IsMessageBlock)
- return ExtBlock.FromRaw(block);
+ ExtBlock block = CommandParser.RawGetBlock(p, name);
+ if (!block.IsInvalid && p.level.BlockProps[block.Index].IsMessageBlock)
+ return block;
// Hardcoded aliases for backwards compatibility
- block = Block.MsgWhite;
- if (name == "white") block = Block.MsgWhite;
- if (name == "black") block = Block.MsgBlack;
- if (name == "air") block = Block.MsgAir;
- if (name == "water") block = Block.MsgWater;
- if (name == "lava") block = Block.MsgLava;
+ block.BlockID = Block.MsgWhite; block.ExtID = 0;
+ if (name == "white") block.BlockID = Block.MsgWhite;
+ if (name == "black") block.BlockID = Block.MsgBlack;
+ if (name == "air") block.BlockID = Block.MsgAir;
+ if (name == "water") block.BlockID = Block.MsgWater;
+ if (name == "lava") block.BlockID = Block.MsgLava;
- allMessage = block == Block.MsgWhite && name != "white";
- if (!Block.Props[block].IsMessageBlock) { Help(p); return ExtBlock.Invalid; }
- return (ExtBlock)block;
+ allMessage = block.BlockID == Block.MsgWhite && name != "white";
+ if (p.level.BlockProps[block.Index].IsMessageBlock) return block;
+
+ Help(p); return ExtBlock.Invalid;
}
bool CheckCommand(Player p, string message) {
@@ -182,44 +180,48 @@ namespace MCGalaxy.Commands.Building {
static ushort U16(object x) { return Convert.ToUInt16(x); }
- static string Format(BlockProps props) {
- if (!props.IsMessageBlock) return null;
+ static string Format(ExtBlock block, Level lvl, BlockProps[] props) {
+ if (!props[block.Index].IsMessageBlock) return null;
// We want to use the simple aliases if possible
- if (Check(props, Block.MsgBlack, "black")) return "black";
- if (Check(props, Block.MsgWhite, "white")) return "white";
- if (Check(props, Block.MsgAir, "air")) return "air";
- if (Check(props, Block.MsgLava, "lava")) return "lava";
- if (Check(props, Block.MsgWater, "water")) return "water";
- return props.Name;
+ if (block.BlockID == Block.MsgBlack) return "black";
+ if (block.BlockID == Block.MsgWhite) return "white";
+ if (block.BlockID == Block.MsgAir) return "air";
+ if (block.BlockID == Block.MsgLava) return "lava";
+ if (block.BlockID == Block.MsgWater) return "water";
+
+ return lvl == null ? Block.Name(block.BlockID) : lvl.BlockName(block);
}
- static bool Check(BlockProps props, byte block, string name) {
- if (props.BlockId != block) return false;
- if (props.Name == "unknown") return false;
-
- block = Block.Byte(name);
- return !Block.Props[block].IsMessageBlock;
+ static void GetAllNames(Player p, List names) {
+ GetCoreNames(names, p.level);
+ for (int i = Block.CpeCount; i < Block.Count; i++) {
+ ExtBlock block = ExtBlock.FromRaw((byte)i);
+ string name = Format(block, p.level, p.level.BlockProps);
+ if (name != null) names.Add(name);
+ }
}
-
- static string FormatCustom(Level lvl, BlockProps props) {
- if (!props.IsMessageBlock) return null;
- BlockDefinition def = lvl.CustomBlockDefs[props.BlockId];
- return def == null ? null : def.Name.Replace(" ", "");
+
+ static void GetCoreNames(List names, Level lvl) {
+ BlockProps[] props = lvl == null ? lvl.BlockProps : Block.Props;
+ for (int i = Block.air; i < Block.Count; i++) {
+ ExtBlock block = new ExtBlock((byte)i, 0);
+ if (block.BlockID == Block.custom_block) continue;
+
+ string name = Format(block, lvl, props);
+ if (name != null) names.Add(name);
+ }
}
public override void Help(Player p) {
Player.Message(p, "%T/mb [block] [message]");
Player.Message(p, "%HPlaces a message in your next block.");
- string blocks = Block.Props.Join(props => Format(props));
- if (!Player.IsSuper(p)) {
- string custom = p.level.BlockProps.Join(props => FormatCustom(p.level, props));
- if (blocks != "" && custom != "")
- blocks = blocks + ", " + custom;
- }
+ List names = new List();
+ if (Player.IsSuper(p)) GetCoreNames(names, null);
+ else GetAllNames(p, names);
- Player.Message(p, "%H Supported blocks: %S{0}", blocks);
+ Player.Message(p, "%H Supported blocks: %S{0}", names.Join());
Player.Message(p, "%H Use | to separate commands, e.g. /say 1 |/say 2");
Player.Message(p, "%H Note: \"@p\" is a placeholder for player who clicked.");
Player.Message(p, "%T/mb show %H- Shows or hides message blocks");
diff --git a/MCGalaxy/Commands/building/CmdPortal.cs b/MCGalaxy/Commands/building/CmdPortal.cs
index a064f30ac..68f6c76af 100644
--- a/MCGalaxy/Commands/building/CmdPortal.cs
+++ b/MCGalaxy/Commands/building/CmdPortal.cs
@@ -55,25 +55,22 @@ namespace MCGalaxy.Commands.Building {
}
ExtBlock GetBlock(Player p, string name) {
- byte block = Block.Byte(name);
- if (Block.Props[block].IsPortal) return (ExtBlock)block;
if (name == "show") { ShowPortals(p); return ExtBlock.Invalid; }
-
- block = BlockDefinition.GetBlock(name, p);
- if (p.level.BlockProps[block].IsPortal)
- return ExtBlock.FromRaw(block);
+ ExtBlock block = CommandParser.RawGetBlock(p, name);
+ if (!block.IsInvalid && p.level.BlockProps[block.Index].IsPortal)
+ return block;
// Hardcoded aliases for backwards compatibility
- block = Block.Invalid;
- if (name == "") block = Block.blue_portal;
- if (name == "blue") block = Block.blue_portal;
- if (name == "orange") block = Block.orange_portal;
- if (name == "air") block = Block.air_portal;
- if (name == "water") block = Block.water_portal;
- if (name == "lava") block = Block.lava_portal;
+ block.BlockID = Block.Invalid; block.ExtID = 0;
+ if (name == "") block.BlockID = Block.blue_portal;
+ if (name == "blue") block.BlockID = Block.blue_portal;
+ if (name == "orange") block.BlockID = Block.orange_portal;
+ if (name == "air") block.BlockID = Block.air_portal;
+ if (name == "water") block.BlockID = Block.water_portal;
+ if (name == "lava") block.BlockID = Block.lava_portal;
- if (!Block.Props[block].IsPortal) { Help(p); return ExtBlock.Invalid; }
- return (ExtBlock)block;
+ if (p.level.BlockProps[block.Index].IsPortal) return block;
+ Help(p); return ExtBlock.Invalid;
}
void EntryChange(Player p, ushort x, ushort y, ushort z, ExtBlock block) {
@@ -184,30 +181,37 @@ namespace MCGalaxy.Commands.Building {
static ushort U16(object x) { return Convert.ToUInt16(x); }
- static string Format(BlockProps props) {
- if (!props.IsPortal) return null;
+ static string Format(ExtBlock block, Level lvl, BlockProps[] props) {
+ if (!props[block.Index].IsPortal) return null;
// We want to use the simple aliases if possible
- if (Check(props, Block.orange_portal, "orange")) return "orange";
- if (Check(props, Block.blue_portal, "blue")) return "blue";
- if (Check(props, Block.air_portal, "air")) return "air";
- if (Check(props, Block.lava_portal, "lava")) return "lava";
- if (Check(props, Block.water_portal, "water")) return "water";
- return props.Name;
- }
-
- static bool Check(BlockProps props, byte block, string name) {
- if (props.BlockId != block) return false;
- if (props.Name == "unknown") return false; // custom blocks
+ if (block.BlockID == Block.orange_portal) return "orange";
+ if (block.BlockID == Block.blue_portal) return "blue";
+ if (block.BlockID == Block.air_portal) return "air";
+ if (block.BlockID == Block.lava_portal) return "lava";
+ if (block.BlockID == Block.water_portal) return "water";
- block = Block.Byte(name);
- return !Block.Props[block].IsPortal;
+ return lvl == null ? Block.Name(block.BlockID) : lvl.BlockName(block);
}
- static string FormatCustom(Level lvl, BlockProps props) {
- if (!props.IsPortal) return null;
- BlockDefinition def = lvl.CustomBlockDefs[props.BlockId];
- return def == null ? null : def.Name.Replace(" ", "");
+ static void GetAllNames(Player p, List names) {
+ GetCoreNames(names, p.level);
+ for (int i = Block.CpeCount; i < Block.Count; i++) {
+ ExtBlock block = ExtBlock.FromRaw((byte)i);
+ string name = Format(block, p.level, p.level.BlockProps);
+ if (name != null) names.Add(name);
+ }
+ }
+
+ static void GetCoreNames(List names, Level lvl) {
+ BlockProps[] props = lvl == null ? lvl.BlockProps : Block.Props;
+ for (int i = Block.air; i < Block.Count; i++) {
+ ExtBlock block = new ExtBlock((byte)i, 0);
+ if (block.BlockID == Block.custom_block) continue;
+
+ string name = Format(block, lvl, props);
+ if (name != null) names.Add(name);
+ }
}
public override void Help(Player p) {
@@ -216,14 +220,11 @@ namespace MCGalaxy.Commands.Building {
Player.Message(p, "%T/portal [block] multi");
Player.Message(p, "%HPlace multiple blocks for entries, then a red block for exit.");
- string blocks = Block.Props.Join(props => Format(props));
- if (!Player.IsSuper(p)) {
- string custom = p.level.BlockProps.Join(props => FormatCustom(p.level, props));
- if (blocks != "" && custom != "")
- blocks = blocks + ", " + custom;
- }
-
- Player.Message(p, "%H Supported blocks: %S{0}", blocks);
+ List names = new List();
+ if (Player.IsSuper(p)) GetCoreNames(names, null);
+ else GetAllNames(p, names);
+
+ Player.Message(p, "%H Supported blocks: %S{0}", names.Join());
Player.Message(p, "%T/portal show %H- Shows portals (green = entry, red = exit)");
}
}
diff --git a/MCGalaxy/Levels/Level.cs b/MCGalaxy/Levels/Level.cs
index 4fa83ba05..838549fdd 100644
--- a/MCGalaxy/Levels/Level.cs
+++ b/MCGalaxy/Levels/Level.cs
@@ -69,10 +69,11 @@ namespace MCGalaxy {
height = Length; depth = Length;
#pragma warning restore 0612
- CustomBlockDefs = new BlockDefinition[256];
+ CustomBlockDefs = new BlockDefinition[Block.Count];
for (int i = 0; i < CustomBlockDefs.Length; i++)
CustomBlockDefs[i] = BlockDefinition.GlobalDefs[i];
- BlockProps = new BlockProps[256];
+
+ BlockProps = new BlockProps[Block.Count * 2];
for (int i = 0; i < BlockProps.Length; i++)
BlockProps[i] = BlockDefinition.GlobalProps[i];