static PaletteEntry Multiply(PaletteEntry entry, ColorDesc rgb) { entry.R = (byte)(entry.R * rgb.R / 255); entry.G = (byte)(entry.G * rgb.G / 255); entry.B = (byte)(entry.B * rgb.B / 255); return(entry); }
void SetZoneProp(Player p, string[] args, Zone zone) { if (args[2].CaselessEq("col")) { ColorDesc desc = default(ColorDesc); if (!CommandParser.GetHex(p, args[3], ref desc)) { return; } zone.Config.ShowColor = args[3]; zone.ShowAll(p.level); } else if (args[2].CaselessEq("alpha")) { if (!CommandParser.GetByte(p, args[3], "Alpha", ref zone.Config.ShowAlpha)) { return; } zone.ShowAll(p.level); } else { Player.Message(p, "?????"); return; } p.level.Save(true); }
/// <summary> Constructs a custom block, with the default properties of the given classic/CPE block. </summary> public static BlockDefinition MakeCustomBlock(BlockID b) { BlockDefinition def = new BlockDefinition(); def.SetBlock(b); def.Name = Name(b); def.CollideType = Collide(b); def.Speed = 1; def.BlocksLight = BlocksLight(b); def.TopTex = topTex[b]; def.BottomTex = bottomTex[b]; def.SetSideTex(sideTex[b]); def.WalkSound = (byte)StepSound(b); def.FullBright = FullBright(b); def.Shape = Draw(b) == DrawType.Sprite ? (byte)0 : (byte)1; def.BlockDraw = Draw(b); if (def.BlockDraw == DrawType.Sprite) { def.BlockDraw = DrawType.Transparent; } def.FogDensity = FogDensity(b); ColorDesc fog = FogColor(b); def.FogR = fog.R; def.FogG = fog.G; def.FogB = fog.B; def.FallBack = (BlockRaw)b; def.MaxX = 16; def.MaxZ = Height(b); def.MaxY = 16; return(def); }
void HandleAdd(Player p, string[] args) { if (args.Length != 4) { Help(p); return; } ImagePalette palette = ImagePalette.Find(args[1]); if (palette == null) { p.Message("Palette {0} does not exist.", args[1]); return; } BlockID block; if (!CommandParser.GetBlock(p, args[2], out block)) { return; } ColorDesc rgb = default(ColorDesc); if (!CommandParser.GetHex(p, args[3], ref rgb)) { return; } PaletteEntry entry = new PaletteEntry(rgb.R, rgb.G, rgb.B, block); AddEntry(p, palette, entry); }
public static byte[] SetTextColor(ColorDesc col) { byte[] buffer = new byte[6]; buffer[0] = Opcode.CpeSetTextColor; buffer[1] = col.R; buffer[2] = col.G; buffer[3] = col.B; buffer[4] = col.A; buffer[5] = col.Index; return(buffer); }
public bool SendSetTextColor(ColorDesc color) { if (!player.Supports(CpeExt.TextColors)) { return(false); } Send(Packet.SetTextColor(color)); return(true); }
/// <summary> Attempts to parse the given argument as a hex color. </summary> public static bool GetHex(Player p, string input, ref ColorDesc col) { ColorDesc tmp; if (!Colors.TryParseHex(input, out tmp)) { p.Message("&W\"#{0}\" is not a valid HEX color.", input); return(false); } col = tmp; return(true); }
public override bool SendSetTextColor(ColorDesc color) { if (!hasTextColors) { return(false); } Send(Packet.SetTextColor(color)); return(true); }
// Not very elegant, because we don't want the % to be escaped like everywhere else internal static string FormatColor(ColorDesc col) { string format = "{0} &{1}({2})%S - %%S{1}, falls back to &{3}%&{3}{3}"; if (col.Code == col.Fallback) { format = "{0} &{1}({2})%S - %&S{1}"; } return(string.Format(format, col.Name, col.Code, Utils.Hex(col.R, col.G, col.B), col.Fallback)); }
void EditHandler(Player p, string[] args) { if (args.Length < 4) { Help(p); return; } char code = ParseColor(p, args[1]); if (code == '\0') { return; } ColorDesc col = Colors.List[code]; if (args[2].CaselessEq("name")) { if (!CheckName(p, args[3])) { return; } p.Message("Set name of {0} to {1}", col.Name, args[3]); col.Name = args[3]; } else if (args[2].CaselessEq("fallback")) { char fallback; if (!CheckFallback(p, args[3], code, out fallback)) { return; } p.Message("Set fallback of {0} to %&S{1}", col.Name, fallback); col.Fallback = fallback; } else if (args[2].CaselessEq("hex") || args[2].CaselessEq("color")) { ColorDesc rgb = default(ColorDesc); if (!CommandParser.GetHex(p, args[3], ref rgb)) { return; } p.Message("Set hex color of {0} to {1}", col.Name, Utils.Hex(rgb.R, rgb.G, rgb.B)); col.R = rgb.R; col.G = rgb.G; col.B = rgb.B; } else { Help(p); return; } Colors.Update(col); }
void SetZoneProp(Player p, string[] args, Zone zone) { ColorDesc desc = default(ColorDesc); if (args.Length < 4) { p.Message("No value provided. See %T/Help zone properties"); return; } string opt = args[2], value = args[3]; Predicate <Player> selector = pl => pl.ZoneIn == zone; if (opt.CaselessEq("alpha")) { float alpha = 0; if (!CommandParser.GetReal(p, value, "Alpha", ref alpha, 0, 1)) { return; } zone.UnshowAll(p.level); zone.Config.ShowAlpha = (byte)(alpha * 255); zone.ShowAll(p.level); } else if (opt.CaselessEq("col")) { if (!CommandParser.GetHex(p, value, ref desc)) { return; } zone.Config.ShowColor = value; zone.ShowAll(p.level); } else if (opt.CaselessEq("motd")) { zone.Config.MOTD = value; OnChangedZone(zone); } else if (CmdEnvironment.Handle(p, selector, opt, value, zone.Config, "zone " + zone.ColoredName)) { OnChangedZone(zone); } else { Help(p, "properties"); return; } p.level.Save(true); }
/// <summary> Attempts to parse the given argument as a hex color. </summary> public static bool GetHex(Player p, string input, ref ColorDesc col) { if (input.Length > 0 && input[0] == '#') { input = input.Substring(1); } if (!Utils.IsValidHex(input)) { Player.Message(p, "\"#{0}\" is not a valid HEX color.", input); return(false); } col = Colors.ParseHex(input); return(true); }
static Color GetCol(char c, Color foreCol) { if (c == 'S' || c == 'f' || c == 'F' || c == '0') { return(foreCol); } Colors.Map(ref c); if (!Colors.IsDefined(c)) { return(foreCol); } ColorDesc col = Colors.Get(c); return(Color.FromArgb(col.R, col.G, col.B)); }
internal static Color LookupColor(char colCode, out Color textCol) { Color rgb = default(Color); ColorDesc col = Colors.Get(colCode); if (col.Undefined) { rgb = Color.White; } else { rgb = Color.FromArgb(col.R, col.G, col.B); } textCol = ColorUtils.CalcBackgroundColor(rgb); return(rgb); }
void AddHandler(Player p, string[] args) { if (args.Length <= 4) { Help(p); return; } char code = args[1][0]; if (Colors.IsStandard(code)) { p.Message("You may only edit standard codes using %T/CustomColors edit"); return; } if (code == ' ' || code == '\0' || code == '\u00a0' || code == '%' || code == '&') { p.Message("{0} must be a standard ASCII character.", code); p.Message("It also cannot be a space, percentage, or ampersand."); return; } char code2 = code; if (Colors.Map(ref code2)) { p.Message("There is already an existing or server defined color with the code " + code + ", you must either use a different code or use %T/CustomColors remove " + code); return; } char fallback; if (!CheckName(p, args[2]) || !CheckFallback(p, args[3], code, out fallback)) { return; } ColorDesc col = default(ColorDesc); if (!CommandParser.GetHex(p, args[4], ref col)) { return; } col.Code = code; col.Fallback = fallback; col.Name = args[2]; Colors.Update(col); p.Message("Successfully added a color."); }
Color GetColor(string name) { string code = Colors.Parse(name); if (code.Length == 0) { return(SystemColors.Control); } if (Colors.IsStandard(code[1])) { return(Color.FromName(name)); } ColorDesc col = Colors.Get(code[1]); return(Color.FromArgb(col.R, col.G, col.B)); }
static void RainbowCallback(SchedulerTask task) { index = (index + 1) % colors.Length; ColorDesc desc = Colors.ParseHex(colors[index]); desc.Code = 'r'; Player[] players = PlayerInfo.Online.Items; foreach (Player p in players) { if (!p.Supports(CpeExt.TextColors)) { continue; } p.Send(Packet.SetTextColor(desc)); } }
internal static Color LookupColor(char colCode, out Color textCol) { Color rgb = default(Color); ColorDesc col = Colors.Get(colCode); if (col.Undefined) { rgb = Color.White; } else { rgb = Color.FromArgb(col.R, col.G, col.B); } double r = Map(rgb.R), g = Map(rgb.G), b = Map(rgb.B); double L = 0.2126 * r + 0.7152 * g + 0.0722 * b; textCol = L > 0.179 ? Color.Black : Color.White; return(rgb); }
void AddHandler(Player p, string[] args) { if (args.Length <= 4) { Help(p); return; } char code = args[1][0]; if (code >= 'A' && code <= 'F') { code += ' '; } if (code == ' ' || code == '\0' || code == '\u00a0' || code == '%' || code == '&') { p.Message("&WColor code cannot be a space, percentage, or ampersand."); return; } if (Colors.IsSystem(code)) { p.Message("&WCannot change system defined color codes using %T/CustomColors"); return; } char fallback; if (!CheckName(p, args[2]) || !CheckFallback(p, args[3], code, out fallback)) { return; } ColorDesc col = default(ColorDesc); if (!CommandParser.GetHex(p, args[4], ref col)) { return; } col.Code = code; col.Fallback = fallback; col.Name = args[2]; Colors.Update(col); p.Message("Successfully added '{0}' color", code); }
void CalcLayerColors() { PaletteEntry[] front = new PaletteEntry[Palette.Entries.Length]; PaletteEntry[] back = new PaletteEntry[Palette.Entries.Length]; ColorDesc sun = Colors.ParseHex("FFFFFF"); ColorDesc dark = Colors.ParseHex("9B9B9B"); if (Utils.IsValidHex(Level.Config.LightColor)) { sun = Colors.ParseHex(Level.Config.LightColor); } if (Utils.IsValidHex(Level.Config.ShadowColor)) { dark = Colors.ParseHex(Level.Config.ShadowColor); } for (int i = 0; i < Palette.Entries.Length; i++) { PaletteEntry entry = Palette.Entries[i]; ExtBlock block = ExtBlock.FromRaw(entry.Raw); BlockDefinition def = Level.GetBlockDef(block); if (def != null && def.FullBright) { front[i] = Multiply(entry, Colors.ParseHex("FFFFFF")); back[i] = Multiply(entry, Colors.ParseHex("FFFFFF")); } else { front[i] = Multiply(entry, sun); back[i] = Multiply(entry, dark); } } selector.SetPalette(front, back); }
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, Level lvl, 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)) { 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)) { bd.SetSideTex(bd.RightTex); step++; } } else if (step == 6) { if (CommandParser.GetUShort(p, value, "Texture ID", ref bd.BottomTex)) { 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; if (!AddBlock(p, lvl, bd, global, cmd)) { return; } BlockDefinition.Save(global, lvl); SetBD(p, global, null); SetStep(p, global, 0); return; } SetStep(p, global, step); SendStepHelp(p, global); }
/// <summary> Sends an update text color code packet to the client </summary> public abstract bool SendSetTextColor(ColorDesc color);
void SetZoneProp(Player p, string[] args, Zone zone) { ColorDesc desc = default(ColorDesc); if (args.Length < 4) { p.Message("No value provided. See &T/Help zone properties"); return; } string opt = args[2], value = args[3]; if (opt.CaselessEq("alpha")) { float alpha = 0; if (!CommandParser.GetReal(p, value, "Alpha", ref alpha, 0, 1)) { return; } zone.UnshowAll(p.level); zone.Config.ShowAlpha = (byte)(alpha * 255); zone.ShowAll(p.level); } else if (opt.CaselessEq("col")) { if (!CommandParser.GetHex(p, value, ref desc)) { return; } zone.Config.ShowColor = value; zone.ShowAll(p.level); } else if (opt.CaselessEq("motd")) { zone.Config.MOTD = value; OnChangedZone(zone); } else if (opt.CaselessEq("text")) { if (value == "null") { zone.Config.Text = ""; } else { bool allCmds = HasExtraPerm(p, "MB", p.Rank, 1); if (!MessageBlock.Validate(p, value, allCmds)) { return; } zone.Config.Text = value; OnChangedZone(zone); } } else if (CmdEnvironment.Handle(p, p.level, opt, value, zone.Config, "zone " + zone.ColoredName)) { OnChangedZone(zone); } else { Help(p, "properties"); return; } p.level.Save(true); }
static void EditHandler(Player p, string[] parts, bool global, string cmd) { if (parts.Length <= 3) { if (parts.Length == 1) { Player.Message(p, "Valid properties: " + helpSections.Keys.Join()); } else if (parts.Length == 3) { Help(p, cmd, "edit " + parts[2]); } else { Help(p, cmd); } return; } ExtBlock block; if (!CheckBlock(p, parts[1], out block)) { return; } BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition def = defs[block.RawID], globalDef = BlockDefinition.GlobalDefs[block.RawID]; if (def == null && block.BlockID < Block.CpeCount) { def = DefaultSet.MakeCustomBlock(block.BlockID); AddBlock(p, def, global, cmd, BlockDefinition.DefaultProps(block)); } if (def != null && !global && def == globalDef) { def = globalDef.Copy(); AddBlock(p, def, global, cmd, BlockDefinition.DefaultProps(block)); } if (!ExistsInScope(def, block, global)) { MessageNoBlock(p, block, global, cmd); return; } string value = parts[3], blockName = def.Name; float fTemp; bool temp = false, changedFallback = false; Level level = p == null ? null : p.level; 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; } break; case "speed": if (!Utils.TryParseDecimal(value, out fTemp) || fTemp < 0.25f || fTemp > 3.96f) { SendEditHelp(p, arg); return; } def.Speed = fTemp; break; case "toptex": if (!EditByte(p, value, "Top texture", ref def.TopTex, arg)) { return; } break; case "alltex": if (!EditByte(p, value, "All textures", ref def.SideTex, arg)) { return; } def.SetAllTex(def.SideTex); break; case "sidetex": if (!EditByte(p, value, "Side texture", ref def.SideTex, arg)) { return; } def.SetSideTex(def.SideTex); break; case "lefttex": if (!EditByte(p, value, "Left texture", ref def.LeftTex, arg)) { return; } break; case "righttex": if (!EditByte(p, value, "Right texture", ref def.RightTex, arg)) { return; } break; case "fronttex": if (!EditByte(p, value, "Front texture", ref def.FrontTex, arg)) { return; } break; case "backtex": if (!EditByte(p, value, "Back texture", ref def.BackTex, arg)) { return; } break; case "bottomtex": if (!EditByte(p, value, "Bottom texture", ref def.BottomTex, arg)) { return; } break; case "blockslight": if (!CommandParser.GetBool(p, value, ref temp)) { SendEditHelp(p, arg); return; } def.BlocksLight = temp; break; case "sound": if (!EditByte(p, value, "Walk sound", ref def.WalkSound, arg)) { return; } break; case "fullbright": if (!CommandParser.GetBool(p, value, ref temp)) { SendEditHelp(p, arg); return; } def.FullBright = temp; break; case "shape": if (!CommandParser.GetBool(p, value, ref temp)) { SendEditHelp(p, arg); return; } def.Shape = temp ? (byte)0 : def.MaxZ; break; case "blockdraw": if (!EditByte(p, value, "Block draw", ref def.BlockDraw, arg)) { return; } break; case "min": if (!ParseCoords(p, value, ref def.MinX, ref def.MinY, ref def.MinZ)) { SendEditHelp(p, arg); return; } break; case "max": if (!ParseCoords(p, value, ref def.MaxX, ref def.MaxY, ref def.MaxZ)) { SendEditHelp(p, arg); return; } break; case "fogdensity": if (!EditByte(p, value, "Fog density", ref def.FogDensity, arg)) { return; } break; case "fogcolor": ColorDesc rgb = default(ColorDesc); if (!CommandParser.GetHex(p, value, ref rgb)) { return; } 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; } changedFallback = true; value = Block.Name(fallback); def.FallBack = fallback; break; case "order": int order = 0; if (!CommandParser.GetInt(p, value, "Inventory order", ref order, 1, 255)) { SendEditHelp(p, arg); return; } def.InventoryOrder = order == def.BlockID ? -1 : order; BlockDefinition.UpdateOrder(def, global, level); BlockDefinition.Save(global, level); Player.Message(p, "Set inventory order for {0} to {1}", blockName, order == def.BlockID ? "default" : order.ToString()); return; default: Player.Message(p, "Unrecognised property: " + arg); return; } Player.Message(p, "Set {0} for {1} to {2}", arg, blockName, value); BlockDefinition.Add(def, defs, level); if (changedFallback) { BlockDefinition.UpdateFallback(global, def.BlockID, level); } }