static void UpdateBlock(Player p, Level lvl, BlockDefinition def, bool global) { BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs; BlockID block = def.GetBlock(); string scope = global ? "global" : "level"; p.Message("Created a new " + scope + " custom block " + def.Name + "(" + def.RawID + ")"); block = def.GetBlock(); BlockDefinition.Add(def, defs, lvl); ResetProps(global, lvl, block, p); }
static bool AddBlock(Player p, Level lvl, BlockDefinition def, bool global, string cmd) { BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs; BlockID block = def.GetBlock(); BlockDefinition old = defs[block]; if (!global && old == BlockDefinition.GlobalDefs[block]) { old = null; } // in case the list is modified before we finish the command. if (old != null) { block = GetFreeBlock(p, global, lvl, cmd); if (block == Block.Invalid) { if (!global) { p.Message("You may also manually specify the same existing id of a global custom block."); } return(false); } def.SetBlock(block); } UpdateBlock(p, lvl, def, global); return(true); }
public static int GetBlock(Player p, string msg, out byte extBlock) { byte block = Block.Byte(msg); extBlock = 0; if (msg.CaselessEq("skip") || msg.CaselessEq("none")) { return(Block.Invalid); } if (block != Block.Invalid) { return(block); } // try treat as a block definition id. block = BlockDefinition.GetBlock(msg, p); if (block == Block.Invalid) { Player.Message(p, "&cThere is no block \"{0}\".", msg); return(-1); } // custom block overriding a core block if (block < Block.CpeCount) { return(block); } extBlock = block; return(Block.custom_block); }
static void ListHandler(Player p, Level lvl, string[] parts, bool global, string cmd) { string modifier = parts.Length > 1 ? parts[1] : ""; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs; List <BlockDefinition> defsInScope = new List <BlockDefinition>(); for (int i = 0; i < defs.Length; i++) { BlockDefinition def = defs[i]; if (def == null) { continue; } BlockID block = def.GetBlock(); if (!ExistsInScope(def, block, global)) { continue; } defsInScope.Add(def); } MultiPageOutput.Output(p, defsInScope, FormatBlock, cmd.Substring(1) + " list", "custom blocks", modifier, true); }
static void ParseBlockDefinitions(NbtCompound cpe, Level lvl) { NbtCompound blocks = (NbtCompound)cpe["BlockDefinitions"]; bool hasBlockDefs = false; foreach (NbtTag tag in blocks) { if (tag.TagType != NbtTagType.Compound) { continue; } NbtCompound props = (NbtCompound)tag; BlockDefinition def = new BlockDefinition(); def.RawID = props["ID"].ByteValue; def.Name = props["Name"].StringValue; def.CollideType = props["CollideType"].ByteValue; def.Speed = props["Speed"].FloatValue; def.BlocksLight = props["TransmitsLight"].ByteValue == 0; def.WalkSound = props["WalkSound"].ByteValue; def.FullBright = props["FullBright"].ByteValue != 0; def.Shape = props["Shape"].ByteValue; def.BlockDraw = props["BlockDraw"].ByteValue; byte[] fog = props["Fog"].ByteArrayValue; def.FogDensity = fog[0]; // Fix for older ClassicalSharp versions which saved wrong value for density = 0 if (def.FogDensity == 0xFF) { def.FogDensity = 0; } def.FogR = fog[1]; def.FogG = fog[2]; def.FogB = fog[3]; byte[] tex = props["Textures"].ByteArrayValue; def.TopTex = tex[0]; def.BottomTex = tex[1]; def.LeftTex = tex[2]; def.RightTex = tex[3]; def.FrontTex = tex[4]; def.BackTex = tex[5]; byte[] coords = props["Coords"].ByteArrayValue; def.MinX = coords[0]; def.MinZ = coords[1]; def.MinY = coords[2]; def.MaxX = coords[3]; def.MaxZ = coords[4]; def.MaxY = coords[5]; // Don't define level custom block if same as global custom block BlockID block = def.GetBlock(); BlockDefinition globalDef = BlockDefinition.GlobalDefs[block]; if (PropsEquals(def, globalDef)) { continue; } lvl.UpdateCustomBlock(block, def); hasBlockDefs = true; } if (hasBlockDefs) { BlockDefinition.Save(false, lvl); } }
internal static byte GetBlock(Player p, string msg, out byte extType, bool checkPlacePerm = true) { byte type = Block.Byte(msg); extType = 0; if (type == Block.Zero) { // try treat as a block definition id. type = BlockDefinition.GetBlock(msg, p); if (type == Block.Zero) { Player.SendMessage(p, "There is no block \"" + msg + "\"."); return(Block.Zero); } extType = type; return(Block.custom_block); } if (checkPlacePerm && !Block.canPlace(p, type)) { Player.SendMessage(p, "Cannot place the block \"" + msg + "\"."); return(Block.Zero); } return(type); }
/// <summary> Attempts to parse the given argument as either a block name or a block ID. </summary> /// <remarks> This does not output any messages to the player. </remarks> public static ExtBlock RawGetBlock(Player p, string input) { BlockDefinition[] defs = p == null ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; byte id; // raw ID is treated specially, before names if (byte.TryParse(input, out id) && (id < Block.CpeCount || defs[id] != null)) { return(ExtBlock.FromRaw(id)); } int raw = BlockDefinition.GetBlock(input, defs); if (raw != -1) { return(ExtBlock.FromRaw((byte)raw)); } id = Block.Byte(input); if (id != Block.Invalid) { return(new ExtBlock(id, 0)); } return(ExtBlock.Invalid); }
byte GetBlock(Player p, string name, out byte extBlock) { extBlock = 0; byte id = Block.Byte(name); if (Block.Props[id].IsPortal) { return(id); } if (name == "show") { ShowPortals(p); return(Block.Invalid); } id = BlockDefinition.GetBlock(name, p); if (p.level.CustomBlockProps[id].IsPortal) { extBlock = id; return(Block.custom_block); } // Hardcoded aliases for backwards compatibility id = Block.Invalid; if (name == "") { id = Block.blue_portal; } if (name == "blue") { id = Block.blue_portal; } if (name == "orange") { id = Block.orange_portal; } if (name == "air") { id = Block.air_portal; } if (name == "water") { id = Block.water_portal; } if (name == "lava") { id = Block.lava_portal; } if (!Block.Props[id].IsPortal) { Help(p); return(Block.Invalid); } return(id); }
byte GetBlock(Player p, string name, out byte extBlock, ref bool allMessage) { extBlock = 0; byte id = Block.Byte(name); if (Block.Props[id].IsMessageBlock) { return(id); } if (name == "show") { ShowMessageBlocks(p); return(Block.Invalid); } id = BlockDefinition.GetBlock(name, p); if (p.level.CustomBlockProps[id].IsMessageBlock) { extBlock = id; return(Block.custom_block); } // Hardcoded aliases for backwards compatibility id = Block.MsgWhite; if (name == "white") { id = Block.MsgWhite; } if (name == "black") { id = Block.MsgBlack; } if (name == "air") { id = Block.MsgAir; } if (name == "water") { id = Block.MsgWater; } if (name == "lava") { id = Block.MsgLava; } allMessage = id == Block.MsgWhite && name != "white"; if (!Block.Props[id].IsMessageBlock) { Help(p); return(Block.Invalid); } return(id); }
static bool AddBlock(Player p, Level lvl, BlockDefinition def, bool global, string cmd, BlockProps props) { BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs; BlockID block = def.GetBlock(); BlockDefinition old = defs[block]; if (!global && old == BlockDefinition.GlobalDefs[block]) { old = null; } // in case the list is modified before we finish the command. if (old != null) { block = GetFreeBlock(global, lvl); if (block == Block.Invalid) { p.Message("There are no custom block ids left, " + "you must " + cmd + " remove a custom block first."); if (!global) { p.Message("You may also manually specify the same existing id of a global custom block."); } return(false); } def.SetBlock(block); } string scope = global ? "global" : "level"; p.Message("Created a new " + scope + " custom block " + def.Name + "(" + def.RawID + ")"); block = def.GetBlock(); BlockDefinition.Add(def, defs, lvl); ResetProps(global, lvl, block, p); return(true); }
static BlockID[] Transform(BlockDefinition[] defs, string[] mirrorDirs, string[] rotateDirs) { BlockID[] transform = new BlockID[Block.ExtendedCount]; for (int i = 0; i < transform.Length; i++) { transform[i] = (BlockID)i; } if (mirrorDirs == null && rotateDirs == null) { return(transform); } // Rotate/Mirror directional blocks for (int i = 0; i < defs.Length; i++) { if (defs[i] == null) { continue; } int dirIndex = defs[i].Name.LastIndexOf('-'); if (dirIndex == -1) { continue; } BlockDefinition transformed = null; if (mirrorDirs != null) { transformed = MirrorTransform(defs, i, dirIndex, mirrorDirs); } else { transformed = RotateTransform(defs, i, dirIndex, rotateDirs); } if (transformed == null) { continue; } BlockID src = defs[i].GetBlock(); transform[src] = transformed.GetBlock(); } return(transform); }
static ExtBlock GetBlock(Player p, BlockProps[] scope, string input) { if (scope == Block.Props) { byte raw; if (!byte.TryParse(input, out raw)) { raw = Block.Byte(input); } if (Block.Name(raw).CaselessEq("unknown")) { Player.Message(p, "&cThere is no block with id or name \"{0}\"", input); return(ExtBlock.Invalid); } return(new ExtBlock(raw, 0)); } else if (scope == BlockDefinition.GlobalProps) { int raw = BlockDefinition.GetBlock(input, BlockDefinition.GlobalDefs); if (raw == -1) { Player.Message(p, "&cThere is no global custom block with id or name \"{0}\"", input); return(ExtBlock.Invalid); } return(ExtBlock.FromRaw((byte)raw)); } else { int raw = BlockDefinition.GetBlock(input, p.level.CustomBlockDefs); if (raw == -1) { Player.Message(p, "&cThere is no level custom block with id or name \"{0}\"", input); return(ExtBlock.Invalid); } if (p.level.CustomBlockDefs[raw] == BlockDefinition.GlobalDefs[raw]) { Player.Message(p, "&cUse %T/BlockProps global &cto modify this custom block."); return(ExtBlock.Invalid); } return(ExtBlock.FromRaw((byte)raw)); } }
byte GetBlock(Player p, BlockProps[] scope, string block) { byte id = 0; if (scope == Block.Props) { if (!byte.TryParse(block, out id)) { id = Block.Byte(block); } if (Block.Name(id).CaselessEq("unknown")) { Player.Message(p, "&cThere is no block with id or name \"{0}\"", block); id = Block.Invalid; } } else if (scope == BlockDefinition.GlobalProps) { id = BlockDefinition.GetBlock(block, BlockDefinition.GlobalDefs); if (id == Block.Invalid) { Player.Message(p, "&cThere is no global custom block with id or name \"{0}\"", block); } } else { id = BlockDefinition.GetBlock(block, p.level.CustomBlockDefs); if (id == Block.Invalid) { Player.Message(p, "&cThere is no level custom block with id or name \"{0}\"", block); } if (p.level.CustomBlockDefs[id] == BlockDefinition.GlobalDefs[id]) { Player.Message(p, "&cUse %T/blockprops global &cto modify this custom block."); return(Block.Invalid); } } return(id); }
static bool DoEdit(Player p, Level lvl, BlockID block, string[] parts, bool global, string cmd) { BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs; BlockDefinition def = defs[block], globalDef = BlockDefinition.GlobalDefs[block]; if (def == null && block < Block.CpeCount) { def = DefaultSet.MakeCustomBlock(block); UpdateBlock(p, lvl, def, global); } if (def != null && !global && def == globalDef) { def = globalDef.Copy(); UpdateBlock(p, lvl, def, global); } if (!ExistsInScope(def, block, global)) { MessageNoBlock(p, block, global, cmd); return(false); } string value = parts[3], blockName = def.Name; bool temp = false, changedFallback = false; string arg = MapPropertyName(parts[2].ToLower()); switch (arg) { case "name": def.Name = value; break; case "collide": if (!EditByte(p, value, "Collide type", ref def.CollideType, arg)) { return(false); } break; case "speed": if (!CommandParser.GetReal(p, value, "Movement speed", ref def.Speed, 0.25f, 3.96f)) { SendEditHelp(p, arg); return(false); } break; case "toptex": if (!EditUShort(p, value, "Top texture", ref def.TopTex, arg)) { return(false); } break; case "alltex": if (!EditUShort(p, value, "All textures", ref def.RightTex, arg)) { return(false); } def.SetAllTex(def.RightTex); break; case "sidetex": if (!EditUShort(p, value, "Side texture", ref def.RightTex, arg)) { return(false); } def.SetSideTex(def.RightTex); break; case "lefttex": if (!EditUShort(p, value, "Left texture", ref def.LeftTex, arg)) { return(false); } break; case "righttex": if (!EditUShort(p, value, "Right texture", ref def.RightTex, arg)) { return(false); } break; case "fronttex": if (!EditUShort(p, value, "Front texture", ref def.FrontTex, arg)) { return(false); } break; case "backtex": if (!EditUShort(p, value, "Back texture", ref def.BackTex, arg)) { return(false); } break; case "bottomtex": if (!EditUShort(p, value, "Bottom texture", ref def.BottomTex, arg)) { return(false); } break; case "blockslight": if (!CommandParser.GetBool(p, value, ref temp)) { SendEditHelp(p, arg); return(false); } def.BlocksLight = temp; break; case "sound": if (!EditByte(p, value, "Walk sound", ref def.WalkSound, arg)) { return(false); } break; case "fullbright": if (!CommandParser.GetBool(p, value, ref temp)) { SendEditHelp(p, arg); return(false); } def.FullBright = temp; break; case "shape": if (!CommandParser.GetBool(p, value, ref temp)) { SendEditHelp(p, arg); return(false); } def.Shape = temp ? (byte)0 : def.MaxZ; break; case "blockdraw": if (!EditByte(p, value, "Block draw", ref def.BlockDraw, arg)) { return(false); } break; case "min": if (!ParseCoords(p, value, ref def.MinX, ref def.MinY, ref def.MinZ)) { SendEditHelp(p, arg); return(false); } break; case "max": if (!ParseCoords(p, value, ref def.MaxX, ref def.MaxY, ref def.MaxZ)) { SendEditHelp(p, arg); return(false); } break; case "fogdensity": if (!EditByte(p, value, "Fog density", ref def.FogDensity, arg)) { return(false); } break; case "fogcolor": ColorDesc rgb = default(ColorDesc); if (!CommandParser.GetHex(p, value, ref rgb)) { return(false); } def.FogR = rgb.R; def.FogG = rgb.G; def.FogB = rgb.B; break; case "fallback": byte fallback = GetFallback(p, value); if (fallback == Block.Invalid) { return(false); } changedFallback = true; value = Block.GetName(p, fallback); def.FallBack = fallback; break; case "order": int order = 0; if (!CommandParser.GetInt(p, value, "Inventory order", ref order, 0, Block.MaxRaw)) { SendEditHelp(p, arg); return(false); } // Don't let multiple blocks be assigned to same order if (order != def.RawID && order != 0) { for (int i = 0; i < defs.Length; i++) { if (defs[i] == null || defs[i].InventoryOrder != order) { continue; } p.Message("Block {0} already had order {1}", defs[i].Name, order); return(false); } } def.InventoryOrder = order == def.RawID ? -1 : order; BlockDefinition.UpdateOrder(def, global, lvl); p.Message("Set inventory order for {0} to {1}", blockName, order == def.RawID ? "default" : order.ToString()); return(true); default: p.Message("Unrecognised property: " + arg); return(false); } p.Message("Set {0} for {1} to {2}", arg, blockName, value); BlockDefinition.Add(def, defs, lvl); if (changedFallback) { BlockDefinition.UpdateFallback(global, def.GetBlock(), lvl); } return(true); }
static void DefineBlockStep(Player p, string value, bool global, string cmd) { string opt = value.ToLower(); int step = GetStep(p, global); BlockDefinition bd = GetBD(p, global); bool temp = false; if (opt == "revert" && step > 2) { if (step == 17 && bd.FogDensity == 0) { step -= 2; } else if (step == 9 && bd.Shape == 0) { step -= 5; } else { step--; } SetStep(p, global, step); SendStepHelp(p, global); return; } if (step == 2) { bd.Name = value; step++; } else if (step == 3) { if (CommandParser.GetBool(p, value, ref temp)) { bd.Shape = temp ? (byte)0 : (byte)16; step++; } } else if (step == 4) { if (CommandParser.GetUShort(p, value, "Texture ID", ref bd.TopTex, 0, 255)) { step += (bd.Shape == 0 ? 5 : 1); // skip other texture steps for sprites if (bd.Shape == 0) { bd.SetAllTex(bd.TopTex); } } } else if (step == 5) { if (CommandParser.GetUShort(p, value, "Texture ID", ref bd.RightTex, 0, 255)) { bd.SetSideTex(bd.RightTex); step++; } } else if (step == 6) { if (CommandParser.GetUShort(p, value, "Texture ID", ref bd.BottomTex, 0, 255)) { step++; } } else if (step == 7) { if (ParseCoords(p, value, ref bd.MinX, ref bd.MinY, ref bd.MinZ)) { step++; } } else if (step == 8) { if (ParseCoords(p, value, ref bd.MaxX, ref bd.MaxY, ref bd.MaxZ)) { step++; } bd.Shape = bd.MaxY; } else if (step == 9) { if (CommandParser.GetByte(p, value, "Collide type", ref bd.CollideType, 0, 7)) { step++; } } else if (step == 10) { if (CommandParser.GetReal(p, value, "Movement speed", ref bd.Speed, 0.25f, 3.96f)) { step++; } } else if (step == 11) { if (CommandParser.GetBool(p, value, ref temp)) { bd.BlocksLight = temp; step++; } } else if (step == 12) { if (CommandParser.GetByte(p, value, "Walk sound", ref bd.WalkSound, 0, 11)) { step++; } } else if (step == 13) { if (CommandParser.GetBool(p, value, ref bd.FullBright)) { step++; } } else if (step == 14) { if (CommandParser.GetByte(p, value, "Block draw", ref bd.BlockDraw, 0, 4)) { step++; } } else if (step == 15) { if (CommandParser.GetByte(p, value, "Fog density", ref bd.FogDensity)) { step += (bd.FogDensity == 0 ? 2 : 1); } } else if (step == 16) { ColorDesc rgb = default(ColorDesc); if (CommandParser.GetHex(p, value, ref rgb)) { bd.FogR = rgb.R; bd.FogG = rgb.G; bd.FogB = rgb.B; step++; } } else if (step == 17) { byte fallback = GetFallback(p, value); if (fallback == Block.Invalid) { SendStepHelp(p, global); return; } bd.FallBack = fallback; BlockID block = bd.GetBlock(); if (!AddBlock(p, bd, global, cmd, Block.Props[block])) { return; } SetBD(p, global, null); SetStep(p, global, 0); return; } SetStep(p, global, step); SendStepHelp(p, global); }
static void ParseBlockDefinitions(NbtCompound cpe, Level lvl) { NbtCompound blocks = (NbtCompound)cpe["BlockDefinitions"]; bool hasBlockDefs = false; foreach (NbtTag tag in blocks) { if (tag.TagType != NbtTagType.Compound) { continue; } NbtCompound props = (NbtCompound)tag; BlockDefinition def = new BlockDefinition(); def.RawID = props["ID"].ByteValue; // can't change "ID" to short since backwards compatibility if (props.Contains("ID2")) { def.RawID = (ushort)props["ID2"].ShortValue; } def.Name = props["Name"].StringValue; def.CollideType = props["CollideType"].ByteValue; def.Speed = props["Speed"].FloatValue; def.BlocksLight = props["TransmitsLight"].ByteValue == 0; def.WalkSound = props["WalkSound"].ByteValue; def.FullBright = props["FullBright"].ByteValue != 0; def.Shape = props["Shape"].ByteValue; def.BlockDraw = props["BlockDraw"].ByteValue; byte[] fog = props["Fog"].ByteArrayValue; def.FogDensity = fog[0]; // Fix for older ClassicalSharp versions which saved wrong value for density = 0 if (def.FogDensity == 0xFF) { def.FogDensity = 0; } def.FogR = fog[1]; def.FogG = fog[2]; def.FogB = fog[3]; byte[] tex = props["Textures"].ByteArrayValue; ImportTexs(def, tex, 0); if (tex.Length > 6) { ImportTexs(def, tex, 6); } byte[] coords = props["Coords"].ByteArrayValue; def.MinX = coords[0]; def.MinZ = coords[1]; def.MinY = coords[2]; def.MaxX = coords[3]; def.MaxZ = coords[4]; def.MaxY = coords[5]; BlockID block = def.GetBlock(); if (block >= Block.ExtendedCount) { Logger.Log(LogType.Warning, "Cannot import custom block {0} (ID {1})", def.Name, def.RawID); continue; } // Don't define level custom block if same as global custom block BlockDefinition globalDef = BlockDefinition.GlobalDefs[block]; if (PropsEquals(def, globalDef)) { continue; } lvl.UpdateCustomBlock(block, def); hasBlockDefs = true; } if (hasBlockDefs) { BlockDefinition.Save(false, lvl); } }