diff --git a/GUI/PropertyWindow/PropertyWindow.Blocks.cs b/GUI/PropertyWindow/PropertyWindow.Blocks.cs index e21a44a60..725f7a2ff 100644 --- a/GUI/PropertyWindow/PropertyWindow.Blocks.cs +++ b/GUI/PropertyWindow/PropertyWindow.Blocks.cs @@ -20,42 +20,56 @@ using System.Collections.Generic; using System.Windows.Forms; using MCGalaxy.Blocks; using BlockID = System.UInt16; +using BlockRaw = System.Byte; namespace MCGalaxy.Gui { public partial class PropertyWindow : Form { bool blockSupressEvents = true; ComboBox[] blockAllowBoxes, blockDisallowBoxes; - byte blockID; + BlockID curBlock; + List blockIDMap; // need to keep a list of changed block perms, because we don't want // to modify the server's live permissions if user clicks 'discard' BlockPerms blockPermsOrig, blockPerms; List blockPermsChanged = new List(); - BlockProps[] blockPropsChanged = new BlockProps[Block.Props.Length]; + BlockProps[] blockPropsChanged = new BlockProps[Block.Props.Length]; void LoadBlocks() { blk_list.Items.Clear(); blockPermsChanged.Clear(); - for (int i = 0; i < Block.Props.Length; i++) { - blockPropsChanged[i] = Block.Props[i]; - blockPropsChanged[i].Changed = false; - if (Block.Undefined((BlockID)i)) continue; - - string name = Block.GetName(null, (byte)i); + blockIDMap = new List(); + + for (int b = 0; b < blockPropsChanged.Length; b++) { + blockPropsChanged[b] = Block.Props[b]; + blockPropsChanged[b].ChangedScope = 0; + + BlockID block = (BlockID)b; + if (!BlockExists(block)) continue; + + string name = Block.GetName(null, block); blk_list.Items.Add(name); + blockIDMap.Add(block); } - if (blk_list.SelectedIndex == -1) + if (blk_list.SelectedIndex == -1) { blk_list.SelectedIndex = 0; + } + } + + bool BlockExists(BlockID b) { + if (b < Block.Count) return !Block.Undefined(b); + BlockRaw raw = (BlockRaw)b; + return BlockDefinition.GlobalDefs[raw] != null; } - void SaveBlocks() { + void SaveBlocks() { if (!BlocksChanged()) { LoadBlocks(); return; } - for (int i = 0; i < blockPropsChanged.Length; i++) { - if (!blockPropsChanged[i].Changed) continue; - Block.Props[i] = blockPropsChanged[i]; + for (int b = 0; b < blockPropsChanged.Length; b++) { + if (blockPropsChanged[b].ChangedScope == 0) continue; + Block.Props[b] = blockPropsChanged[b]; } foreach (BlockPerms perms in blockPermsChanged) { @@ -63,28 +77,28 @@ namespace MCGalaxy.Gui { } BlockPerms.ResendAllBlockPermissions(); - BlockProps.Save("core", Block.Props, Block.CorePropsLock, null); + BlockProps.Save("default", Block.Props, Block.PropsLock, 1); BlockPerms.Save(); Block.SetBlocks(); LoadBlocks(); } bool BlocksChanged() { - for (int i = 0; i < blockPropsChanged.Length; i++) { - if (blockPropsChanged[i].Changed) return true; + for (int b = 0; b < blockPropsChanged.Length; b++) { + if (blockPropsChanged[b].ChangedScope != 0) return true; } return blockPermsChanged.Count > 0; } void blk_list_SelectedIndexChanged(object sender, EventArgs e) { - blockID = Block.Byte(blk_list.SelectedItem.ToString()); - blockPermsOrig = BlockPerms.List[blockID]; - blockPerms = blockPermsChanged.Find(p => p.ID == blockID); + curBlock = blockIDMap[blk_list.SelectedIndex]; + blockPermsOrig = BlockPerms.List[curBlock]; + blockPerms = blockPermsChanged.Find(p => p.ID == curBlock); BlockInitSpecificArrays(); blockSupressEvents = true; - BlockProps props = blockPropsChanged[blockID]; + BlockProps props = blockPropsChanged[curBlock]; blk_cbMsgBlock.Checked = props.IsMessageBlock; blk_cbPortal.Checked = props.IsPortal; blk_cbDeath.Checked = props.KillerBlock; @@ -96,7 +110,7 @@ namespace MCGalaxy.Gui { blk_cbRails.Checked = props.IsRails; blk_cbLava.Checked = props.LavaKills; blk_cbWater.Checked = props.WaterKills; - + BlockPerms perms = blockPerms != null ? blockPerms : blockPermsOrig; GuiPerms.SetDefaultIndex(blk_cmbMin, perms.MinRank); GuiPerms.SetSpecificPerms(perms.Allowed, blockAllowBoxes); @@ -161,49 +175,55 @@ namespace MCGalaxy.Gui { void blk_cbMsgBlock_CheckedChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].IsMessageBlock = blk_cbMsgBlock.Checked; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + blockPropsChanged[curBlock].IsMessageBlock = blk_cbMsgBlock.Checked; + MarkBlockPropsChanged(); } void blk_cbPortal_CheckedChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].IsPortal = blk_cbPortal.Checked; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + blockPropsChanged[curBlock].IsPortal = blk_cbPortal.Checked; + MarkBlockPropsChanged(); } void blk_cbDeath_CheckedChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].KillerBlock = blk_cbDeath.Checked; + blockPropsChanged[curBlock].KillerBlock = blk_cbDeath.Checked; blk_txtDeath.Enabled = blk_cbDeath.Checked; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + MarkBlockPropsChanged(); } void blk_txtDeath_TextChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].DeathMessage = blk_txtDeath.Text; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + blockPropsChanged[curBlock].DeathMessage = blk_txtDeath.Text; + MarkBlockPropsChanged(); } void blk_cbDoor_CheckedChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].IsDoor = blk_cbDoor.Checked; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + blockPropsChanged[curBlock].IsDoor = blk_cbDoor.Checked; + MarkBlockPropsChanged(); } void blk_cbTdoor_CheckedChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].IsTDoor = blk_cbTdoor.Checked; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + blockPropsChanged[curBlock].IsTDoor = blk_cbTdoor.Checked; + MarkBlockPropsChanged(); } void blk_cbRails_CheckedChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].IsRails = blk_cbRails.Checked; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + blockPropsChanged[curBlock].IsRails = blk_cbRails.Checked; + MarkBlockPropsChanged(); } void blk_cbLava_CheckedChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].LavaKills = blk_cbLava.Checked; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + blockPropsChanged[curBlock].LavaKills = blk_cbLava.Checked; + MarkBlockPropsChanged(); } void blk_cbWater_CheckedChanged(object sender, EventArgs e) { - blockPropsChanged[blockID].WaterKills = blk_cbWater.Checked; - blockPropsChanged[blockID].Changed = !blockSupressEvents; + blockPropsChanged[curBlock].WaterKills = blk_cbWater.Checked; + MarkBlockPropsChanged(); + } + + void MarkBlockPropsChanged() { + // don't mark props as changed when supressing events + int changed = blockSupressEvents ? 0 : 1; + blockPropsChanged[curBlock].ChangedScope = (byte)changed; } } } diff --git a/MCGalaxy/Blocks/Block.CoreProps.cs b/MCGalaxy/Blocks/Block.CoreProps.cs index 91027bd78..f7c4b878d 100644 --- a/MCGalaxy/Blocks/Block.CoreProps.cs +++ b/MCGalaxy/Blocks/Block.CoreProps.cs @@ -18,104 +18,118 @@ using System; using System.Collections.Generic; using MCGalaxy.Blocks; +using BlockID = System.UInt16; namespace MCGalaxy { public sealed partial class Block { - public static BlockProps[] Props = new BlockProps[Block.Count]; - public static readonly object CorePropsLock = new object(); + public static BlockProps[] Props = new BlockProps[Block.ExtendedCount]; + public static readonly object PropsLock = new object(); public static Dictionary Aliases = new Dictionary(); - static void SetCoreProperties() { - for (int i = 0; i < Block.Count; i++) - Props[i] = BlockProps.MakeDefault(); - for (int i = 0; i < Block.Count; i++) { - if ((i >= Op_Glass && i <= Op_Lava) || i == Invalid || i == RocketStart || i == Bedrock) { - Props[i].OPBlock = true; + internal static void ChangeGlobalProps(BlockID block, BlockProps props) { + Level[] loaded = LevelInfo.Loaded.Items; + Block.Props[block] = props; + + foreach (Level lvl in loaded) { + if (lvl.HasCustomProps(block)) continue; + lvl.Props[block] = props; + lvl.UpdateBlockHandler(block); + } + } + + internal static void MakeDefaultProps(BlockProps[] props) { + for (int b = 0; b < props.Length; b++) { + props[b] = BlockProps.MakeDefault(); + if ((b >= Op_Glass && b <= Op_Lava) || b == Invalid || b == RocketStart || b == Bedrock) { + props[b].OPBlock = true; } - if ((i >= tDoor_Log && i <= tDoor_Green) || (i >= tDoor_TNT && i <= tDoor_Lava)) { - Props[i].IsTDoor = true; + if ((b >= tDoor_Log && b <= tDoor_Green) || (b >= tDoor_TNT && b <= tDoor_Lava)) { + props[b].IsTDoor = true; } - if (i >= MB_White && i <= MB_Lava) { - Props[i].IsMessageBlock = true; + if (b >= MB_White && b <= MB_Lava) { + props[b].IsMessageBlock = true; } - if (i == Portal_Blue || i == Portal_Orange || (i >= Portal_Air && i <= Portal_Lava)) { - Props[i].IsPortal = true; + if (b == Portal_Blue || b == Portal_Orange || (b >= Portal_Air && b <= Portal_Lava)) { + props[b].IsPortal = true; } // oDoor blocks - if (i >= oDoor_Log && i <= oDoor_Wood) { - Props[i].oDoorBlock = (ushort)(oDoor_Log_air + (i - oDoor_Log)); + if (b >= oDoor_Log && b <= oDoor_Wood) { + props[b].oDoorBlock = (ushort)(oDoor_Log_air + (b - oDoor_Log)); } - if (i >= oDoor_Green && i <= oDoor_Water) { - Props[i].oDoorBlock = (ushort)(oDoor_Green_air + (i - oDoor_Green)); + if (b >= oDoor_Green && b <= oDoor_Water) { + props[b].oDoorBlock = (ushort)(oDoor_Green_air + (b - oDoor_Green)); } - if (i >= oDoor_Log_air && i <= oDoor_Wood_air) { - Props[i].oDoorBlock = (ushort)(oDoor_Log + (i - oDoor_Log_air)); + if (b >= oDoor_Log_air && b <= oDoor_Wood_air) { + props[b].oDoorBlock = (ushort)(oDoor_Log + (b - oDoor_Log_air)); } - if (i >= oDoor_Green_air && i <= oDoor_Water_air) { - Props[i].oDoorBlock = (ushort)(oDoor_Green + (i - oDoor_Green_air)); + if (b >= oDoor_Green_air && b <= oDoor_Water_air) { + props[b].oDoorBlock = (ushort)(oDoor_Green + (b - oDoor_Green_air)); } - if ((i >= Red && i <= White) || (i >= LightPink && i <= turquoise)) { - Props[i].LavaKills = true; + if ((b >= Red && b <= White) || (b >= LightPink && b <= turquoise)) { + props[b].LavaKills = true; } - if (i == Air || i == Sapling || (i >= Dandelion && i <= RedMushroom)) { - Props[i].LavaKills = true; - Props[i].WaterKills = true; + if (b == Air || b == Sapling || (b >= Dandelion && b <= RedMushroom)) { + props[b].LavaKills = true; + props[b].WaterKills = true; } // Door blocks - if (i >= Door_Obsidian && i <= Door_Slab) Props[i].IsDoor = true; - if (i >= Door_Iron && i <= Door_Bookshelf) Props[i].IsDoor = true; - if (i >= Door_Orange && i <= Door_White) Props[i].IsDoor = true; + if (b >= Door_Obsidian && b <= Door_Slab) props[b].IsDoor = true; + if (b >= Door_Iron && b <= Door_Bookshelf) props[b].IsDoor = true; + if (b >= Door_Orange && b <= Door_White) props[b].IsDoor = true; } // Other door blocks, since they aren't in a consistent order - Props[Door_Log].IsDoor = true; - Props[Door_Red].IsDoor = true; - Props[Door_Cobblestone].IsDoor = true; - Props[Door_Gold].IsDoor = true; - Props[Door_Air].IsDoor = true; - Props[Door_AirActivatable].IsDoor = true; - Props[Door_Water].IsDoor = true; - Props[Door_Lava].IsDoor = true; + props[Door_Log].IsDoor = true; + props[Door_Red].IsDoor = true; + props[Door_Cobblestone].IsDoor = true; + props[Door_Gold].IsDoor = true; + props[Door_Air].IsDoor = true; + props[Door_AirActivatable].IsDoor = true; + props[Door_Water].IsDoor = true; + props[Door_Lava].IsDoor = true; // Block specific properties - Props[Wood].LavaKills = true; Props[Log].LavaKills = true; - Props[Sponge].LavaKills = true; Props[Bookshelf].LavaKills = true; - Props[Leaves].LavaKills = true; Props[Crate].LavaKills = true; - Props[Red].IsRails = true; Props[Op_Air].IsRails = true; - Props[Slab].StackBlock = DoubleSlab; - Props[CobblestoneSlab].StackBlock = Cobblestone; - Props[Water].Drownable = true; Props[StillWater].Drownable = true; - Props[Lava].Drownable = true; Props[StillLava].Drownable = true; - Props[Dirt].GrassBlock = Block.Grass; Props[Grass].DirtBlock = Block.Dirt; + props[Wood].LavaKills = true; props[Log].LavaKills = true; + props[Sponge].LavaKills = true; props[Bookshelf].LavaKills = true; + props[Leaves].LavaKills = true; props[Crate].LavaKills = true; + props[Red].IsRails = true; props[Op_Air].IsRails = true; + props[Slab].StackBlock = DoubleSlab; + props[CobblestoneSlab].StackBlock = Cobblestone; + props[Water].Drownable = true; props[StillWater].Drownable = true; + props[Lava].Drownable = true; props[StillLava].Drownable = true; + props[Dirt].GrassBlock = Block.Grass; props[Grass].DirtBlock = Block.Dirt; // Block specific physics properties - Props[Block.Bird_Black].AnimalAI = AnimalAI.Fly; - Props[Block.Bird_White].AnimalAI = AnimalAI.Fly; - Props[Block.Bird_Lava].AnimalAI = AnimalAI.Fly; - Props[Block.Bird_Water].AnimalAI = AnimalAI.Fly; + props[Block.Bird_Black].AnimalAI = AnimalAI.Fly; + props[Block.Bird_White].AnimalAI = AnimalAI.Fly; + props[Block.Bird_Lava].AnimalAI = AnimalAI.Fly; + props[Block.Bird_Water].AnimalAI = AnimalAI.Fly; - Props[Block.Bird_Red].AnimalAI = AnimalAI.KillerAir; - Props[Block.Bird_Blue].AnimalAI = AnimalAI.KillerAir; - Props[Block.Bird_Killer].AnimalAI = AnimalAI.KillerAir; + props[Block.Bird_Red].AnimalAI = AnimalAI.KillerAir; + props[Block.Bird_Blue].AnimalAI = AnimalAI.KillerAir; + props[Block.Bird_Killer].AnimalAI = AnimalAI.KillerAir; - Props[Block.Fish_Betta].AnimalAI = AnimalAI.KillerWater; - Props[Block.Fish_Shark].AnimalAI = AnimalAI.KillerWater; - Props[Block.Fish_LavaShark].AnimalAI = AnimalAI.KillerLava; - - Props[Block.Fish_Gold].AnimalAI = AnimalAI.FleeWater; - Props[Block.Fish_Salmon].AnimalAI = AnimalAI.FleeWater; - Props[Block.Fish_Sponge].AnimalAI = AnimalAI.FleeWater; + props[Block.Fish_Betta].AnimalAI = AnimalAI.KillerWater; + props[Block.Fish_Shark].AnimalAI = AnimalAI.KillerWater; + props[Block.Fish_LavaShark].AnimalAI = AnimalAI.KillerLava; + props[Block.Fish_Gold].AnimalAI = AnimalAI.FleeWater; + props[Block.Fish_Salmon].AnimalAI = AnimalAI.FleeWater; + props[Block.Fish_Sponge].AnimalAI = AnimalAI.FleeWater; + } + + static void SetCoreProperties() { + MakeDefaultProps(Props); SetDefaultNames(); SetDefaultDeaths(); } - + internal static void SetDefaultNames() { string[] names = new string[] { "Air", "Stone", "Grass", "Dirt", "Cobblestone", "Wood", "Sapling", "Bedrock", "Active_Water", "Water", "Active_Lava", "Lava", diff --git a/MCGalaxy/Blocks/Block.cs b/MCGalaxy/Blocks/Block.cs index 08ec83792..99315af95 100644 --- a/MCGalaxy/Blocks/Block.cs +++ b/MCGalaxy/Blocks/Block.cs @@ -16,6 +16,7 @@ permissions and limitations under the Licenses. */ using System; +using System.IO; using MCGalaxy.Blocks; using MCGalaxy.Maths; using BlockID = System.UInt16; @@ -151,15 +152,23 @@ namespace MCGalaxy { def.MaxX * 2, def.MaxZ * 2, def.MaxY * 2); } - if (block >= Block.Extended) return new AABB(0, 0, 0, 32, 32, 32); + if (block >= Block.Extended) return new AABB(0, 0, 0, 32, 32, 32); BlockID core = Convert(block); return new AABB(0, 0, 0, 32, DefaultSet.Height(core) * 2, 32); - } + } public static void SetBlocks() { SetCoreProperties(); - BlockProps.Load("core", Props, CorePropsLock, false); - BlockDefinition.UpdateGlobalBlockProps(); + string propsPath = BlockProps.PropsPath("default"); + + // backwards compatibility with older versions + if (!File.Exists(propsPath)) { + BlockProps.Load("core", Props, PropsLock, 1, false); + BlockProps.Load("global", Props, PropsLock, 1, true); + } else { + BlockProps.Load("default", Props, PropsLock, 1, false); + } + BlockPerms.Load(); UpdateLoadedLevels(); } @@ -169,7 +178,7 @@ namespace MCGalaxy { foreach (Level lvl in loaded) { lvl.UpdateBlockProps(); lvl.UpdateBlockHandlers(); - } + } } public static BlockID FromRaw(byte raw) { @@ -181,6 +190,7 @@ namespace MCGalaxy { } public static BlockID MapOldRaw(BlockID raw) { + // old raw form was: 0 - 65 core block ids, 66 - 255 custom block ids return IsPhysicsType(raw) ? ((BlockID)(Block.Extended | raw)) : raw; } diff --git a/MCGalaxy/Blocks/BlockDefinitions.cs b/MCGalaxy/Blocks/BlockDefinitions.cs index 79e7bb5fe..e9baccc97 100644 --- a/MCGalaxy/Blocks/BlockDefinitions.cs +++ b/MCGalaxy/Blocks/BlockDefinitions.cs @@ -50,7 +50,6 @@ namespace MCGalaxy { public const string GlobalPath = "blockdefs/global.json", GlobalBackupPath = "blockdefs/global.json.bak"; public static BlockDefinition[] GlobalDefs; - public static BlockProps[] GlobalProps = new BlockProps[Block.Count]; internal static readonly object GlobalPropsLock = new object(); public BlockDefinition Copy() { @@ -145,26 +144,6 @@ namespace MCGalaxy { if (oldDefs != null) UpdateLoadedLevels(oldDefs); } - public static void UpdateGlobalBlockProps() { - for (int i = 0; i < GlobalProps.Length; i++) { - BlockID_ block = Block.FromRaw((byte)i); - GlobalProps[i] = BlockProps.MakeDefault(); - GlobalProps[i] = DefaultProps(block); - } - BlockProps.Load("global", GlobalProps, GlobalPropsLock, false); - } - - internal static BlockProps DefaultProps(BlockID_ block) { - BlockRaw raw = (BlockRaw)block; - if (Block.IsPhysicsType(block)) { - return Block.Props[block]; - } else if (block < Block.Extended && GlobalDefs[raw] == null) { - return Block.Props[raw]; - } else { - return GlobalProps[raw]; - } - } - static void UpdateLoadedLevels(BlockDefinition[] oldGlobalDefs) { Level[] loaded = LevelInfo.Loaded.Items; foreach (Level lvl in loaded) { @@ -172,7 +151,7 @@ namespace MCGalaxy { if (lvl.CustomBlockDefs[i] != oldGlobalDefs[i]) continue; BlockID_ block = Block.FromRaw((byte)i); - lvl.Props[block] = DefaultProps(block); + lvl.Props[block] = Block.Props[block]; lvl.UpdateCustomBlock((BlockRaw)block, GlobalDefs[i]); } } diff --git a/MCGalaxy/Blocks/BlockPerms.cs b/MCGalaxy/Blocks/BlockPerms.cs index 36d6a5184..edfbad8b1 100644 --- a/MCGalaxy/Blocks/BlockPerms.cs +++ b/MCGalaxy/Blocks/BlockPerms.cs @@ -163,13 +163,12 @@ namespace MCGalaxy.Blocks { } static void SetDefaultPerms() { - BlockProps defProps = BlockProps.MakeDefault(); - for (int i = 0; i < Block.ExtendedCount; i++) { + for (BlockID block = 0; block < Block.ExtendedCount; block++) { BlockPerms perms = new BlockPerms(); - perms.ID = (BlockID)i; - BlockProps props = i < Block.Count ? Block.Props[i] : defProps; + perms.ID = block; + BlockProps props = Block.Props[block]; - if (i == Block.Invalid) { + if (block == Block.Invalid) { perms.MinRank = LevelPermission.Admin; } else if (props.OPBlock) { perms.MinRank = LevelPermission.Operator; @@ -178,9 +177,9 @@ namespace MCGalaxy.Blocks { } else if (props.IsPortal || props.IsMessageBlock) { perms.MinRank = LevelPermission.AdvBuilder; } else { - perms.MinRank = DefaultPerm(i); + perms.MinRank = DefaultPerm(block); } - List[i] = perms; + List[block] = perms; } } diff --git a/MCGalaxy/Blocks/BlockProperties.cs b/MCGalaxy/Blocks/BlockProperties.cs index 938a973cb..5b87be0df 100644 --- a/MCGalaxy/Blocks/BlockProperties.cs +++ b/MCGalaxy/Blocks/BlockProperties.cs @@ -75,7 +75,7 @@ namespace MCGalaxy.Blocks { public BlockID DirtBlock; /// Whether the properties for this block have been modified and hence require saving. - public bool Changed; + public byte ChangedScope; public static BlockProps MakeDefault() { BlockProps props = default(BlockProps); @@ -86,29 +86,27 @@ namespace MCGalaxy.Blocks { } - public static void Save(string group, BlockProps[] scope, object locker, Predicate selector) { + public static void Save(string group, BlockProps[] list, object locker, byte scope) { lock (locker) { if (!Directory.Exists("blockprops")) Directory.CreateDirectory("blockprops"); - SaveCore(group, scope, selector); + SaveCore(group, list, scope); } } - static void SaveCore(string group, BlockProps[] scope, Predicate selector) { + static void SaveCore(string group, BlockProps[] list, byte scope) { using (StreamWriter w = new StreamWriter("blockprops/" + group + ".txt")) { w.WriteLine("# This represents the physics properties for blocks, in the format of:"); w.WriteLine("# id : Is rails : Is tdoor : Is door : Is message block : Is portal : " + "Killed by water : Killed by lava : Kills players : death message : " + "Animal AI type : Stack block : Is OP block : oDoor block : Drownable : " + "Grass block : Dirt block"); - for (int i = 0; i < scope.Length; i++) { - if (!scope[i].Changed || (selector != null && !selector(i))) continue; - BlockProps props = scope[i]; - // Convert ext to raw ids - int id = i >= Block.Count ? (i - Block.Count) : i; + for (int b = 0; b < list.Length; b++) { + if ((list[b].ChangedScope & scope) == 0) continue; + BlockProps props = list[b]; string deathMsg = props.DeathMessage == null ? "" : props.DeathMessage.Replace(":", "\\;"); - w.WriteLine(id + ":" + props.IsRails + ":" + props.IsTDoor + ":" + props.IsDoor + ":" + w.WriteLine(b + ":" + props.IsRails + ":" + props.IsTDoor + ":" + props.IsDoor + ":" + props.IsMessageBlock + ":" + props.IsPortal + ":" + props.WaterKills + ":" + props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg + ":" + (byte)props.AnimalAI + ":" + props.StackBlock + ":" + props.OPBlock + ":" @@ -118,71 +116,71 @@ namespace MCGalaxy.Blocks { } } - public static void Load(string group, BlockProps[] scope, object locker, bool lbScope) { + public static string PropsPath(string group) { return "blockprops/" + group + ".txt"; } + + public static void Load(string group, BlockProps[] list, object locker, byte scope, bool mapOld) { lock (locker) { if (!Directory.Exists("blockprops")) return; - if (!File.Exists("blockprops/" + group + ".txt")) return; - LoadCore(group, scope, lbScope); + string path = PropsPath(group); + if (File.Exists(path)) LoadCore(path, list, scope, mapOld); } } - static void LoadCore(string group, BlockProps[] scope, bool lbScope) { - string[] lines = File.ReadAllLines("blockprops/" + group + ".txt"); + static void LoadCore(string path, BlockProps[] list, byte scope, bool mapOld) { + string[] lines = File.ReadAllLines(path); for (int i = 0; i < lines.Length; i++) { string line = lines[i].Trim(); if (line.Length == 0 || line[0] == '#') continue; string[] parts = line.Split(':'); if (parts.Length < 10) { - Logger.Log(LogType.Warning, "Invalid line \"{0}\" in {1} block properties", line, group); + Logger.Log(LogType.Warning, "Invalid line \"{0}\" in {1}", line, path); continue; } - // TODO fix fix fix - byte raw; - if (!Byte.TryParse(parts[0], out raw)) { - Logger.Log(LogType.Warning, "Invalid line \"{0}\" in {1} block properties", line, group); + BlockID b; + if (!BlockID.TryParse(parts[0], out b)) { + Logger.Log(LogType.Warning, "Invalid line \"{0}\" in {1}", line, path); continue; } - int idx = raw; - if (lbScope && raw >= Block.CpeCount) idx += Block.Count; + if (mapOld) b = Block.MapOldRaw(b); - bool.TryParse(parts[1], out scope[idx].IsRails); - bool.TryParse(parts[2], out scope[idx].IsTDoor); - bool.TryParse(parts[3], out scope[idx].IsDoor); - bool.TryParse(parts[4], out scope[idx].IsMessageBlock); - bool.TryParse(parts[5], out scope[idx].IsPortal); - bool.TryParse(parts[6], out scope[idx].WaterKills); - bool.TryParse(parts[7], out scope[idx].LavaKills); - bool.TryParse(parts[8], out scope[idx].KillerBlock); + bool.TryParse(parts[1], out list[b].IsRails); + bool.TryParse(parts[2], out list[b].IsTDoor); + bool.TryParse(parts[3], out list[b].IsDoor); + bool.TryParse(parts[4], out list[b].IsMessageBlock); + bool.TryParse(parts[5], out list[b].IsPortal); + bool.TryParse(parts[6], out list[b].WaterKills); + bool.TryParse(parts[7], out list[b].LavaKills); + bool.TryParse(parts[8], out list[b].KillerBlock); - scope[idx].Changed = true; - scope[idx].DeathMessage = parts[9].Replace("\\;", ":"); - if (scope[idx].DeathMessage.Length == 0) - scope[idx].DeathMessage = null; + list[b].ChangedScope = scope; + list[b].DeathMessage = parts[9].Replace("\\;", ":"); + if (list[b].DeathMessage.Length == 0) + list[b].DeathMessage = null; if (parts.Length > 10) { byte ai; byte.TryParse(parts[10], out ai); - scope[idx].AnimalAI = (AnimalAI)ai; + list[b].AnimalAI = (AnimalAI)ai; } if (parts.Length > 11) { - BlockID.TryParse(parts[11], out scope[idx].StackBlock); - scope[idx].StackBlock = Block.MapOldRaw(scope[idx].StackBlock); + BlockID.TryParse(parts[11], out list[b].StackBlock); + list[b].StackBlock = Block.MapOldRaw(list[b].StackBlock); } if (parts.Length > 12) { - bool.TryParse(parts[12], out scope[idx].OPBlock); + bool.TryParse(parts[12], out list[b].OPBlock); } if (parts.Length > 13) { - BlockID.TryParse(parts[13], out scope[idx].oDoorBlock); + BlockID.TryParse(parts[13], out list[b].oDoorBlock); } if (parts.Length > 14) { - bool.TryParse(parts[14], out scope[idx].Drownable); + bool.TryParse(parts[14], out list[b].Drownable); } if (parts.Length > 15) { - BlockID.TryParse(parts[15], out scope[idx].GrassBlock); + BlockID.TryParse(parts[15], out list[b].GrassBlock); } if (parts.Length > 16) { - BlockID.TryParse(parts[16], out scope[idx].DirtBlock); + BlockID.TryParse(parts[16], out list[b].DirtBlock); } } } diff --git a/MCGalaxy/Commands/CPE/CustomBlockCommand.cs b/MCGalaxy/Commands/CPE/CustomBlockCommand.cs index 5bbdc252c..c613ae0cb 100644 --- a/MCGalaxy/Commands/CPE/CustomBlockCommand.cs +++ b/MCGalaxy/Commands/CPE/CustomBlockCommand.cs @@ -119,7 +119,7 @@ namespace MCGalaxy.Commands.CPE { if (srcDef == null) { MessageNoBlock(p, src, global, cmd); return; } if (ExistsInScope(dstDef, dst, global)) { MessageAlreadyBlock(p, dst, global, cmd); return; } - BlockProps props = global ? BlockDefinition.GlobalProps[srcRaw] : p.level.Props[src]; + BlockProps props = global ? Block.Props[src] : p.level.Props[src]; dstDef = srcDef.Copy(); dstDef.BlockID = dstRaw; dstDef.InventoryOrder = -1; @@ -287,8 +287,7 @@ namespace MCGalaxy.Commands.CPE { bd.FallBack = fallback; BlockID block = Block.FromRaw(bd.BlockID); - BlockProps props = BlockDefinition.DefaultProps(block); - if (!AddBlock(p, bd, global, cmd, props)) return; + if (!AddBlock(p, bd, global, cmd, Block.Props[block])) return; SetBD(p, global, null); SetStep(p, global, 0); @@ -314,17 +313,17 @@ namespace MCGalaxy.Commands.CPE { BlockID block; if (!CheckBlock(p, parts[1], out block)) return; BlockRaw raw = (BlockRaw)block; - + BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition def = defs[raw], globalDef = BlockDefinition.GlobalDefs[raw]; if (def == null && block < Block.CpeCount) { def = DefaultSet.MakeCustomBlock(block); - AddBlock(p, def, global, cmd, BlockDefinition.DefaultProps(block)); + AddBlock(p, def, global, cmd, Block.Props[block]); } if (def != null && !global && def == globalDef) { def = globalDef.Copy(); - AddBlock(p, def, global, cmd, BlockDefinition.DefaultProps(block)); + AddBlock(p, def, global, cmd, Block.Props[block]); } if (!ExistsInScope(def, block, global)) { MessageNoBlock(p, block, global, cmd); return; } @@ -432,7 +431,7 @@ namespace MCGalaxy.Commands.CPE { 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, + Player.Message(p, "Set inventory order for {0} to {1}", blockName, order == def.BlockID ? "default" : order.ToString()); return; default: @@ -557,39 +556,19 @@ namespace MCGalaxy.Commands.CPE { if (!global) { p.level.Props[block] = props; p.level.UpdateBlockHandler(block); - return; - } - - BlockRaw raw = (BlockRaw)block; - BlockDefinition.GlobalProps[raw] = props; - Level[] loaded = LevelInfo.Loaded.Items; - - foreach (Level lvl in loaded) { - if (lvl.CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw]) continue; - lvl.Props[block] = props; - lvl.UpdateBlockHandler(block); + } else { + Block.ChangeGlobalProps(block, props); } } static void RemoveBlockProps(bool global, BlockID block, Player p) { - // Level block reverts to using global block if (!global) { - p.level.Props[block] = BlockDefinition.DefaultProps(block); + p.level.Props[block] = Block.Props[block]; p.level.UpdateBlockHandler(block); - return; - } - - BlockProps props = BlockProps.MakeDefault(); - if (block < Block.Extended) props = Block.Props[block]; - - BlockRaw raw = (BlockRaw)block; - BlockDefinition.GlobalProps[raw] = props; - Level[] loaded = LevelInfo.Loaded.Items; - - foreach (Level lvl in loaded) { - if (lvl.CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw]) continue; - lvl.Props[block] = BlockDefinition.GlobalProps[raw]; - lvl.UpdateBlockHandler(block); + } else { + BlockProps[] defProps = new BlockProps[Block.ExtendedCount]; + Block.MakeDefaultProps(defProps); + Block.ChangeGlobalProps(block, defProps[block]); } } @@ -724,7 +703,7 @@ namespace MCGalaxy.Commands.CPE { } internal static void Help(Player p, string cmd, string args) { - if (!args.CaselessStarts("edit ")) { Help(p, cmd); return; } + if (!args.CaselessStarts("edit ")) { Help(p, cmd); return; } string prop = args.Substring(args.IndexOf(' ') + 1); prop = MapPropertyName(prop.ToLower()); diff --git a/MCGalaxy/Commands/World/CmdBlockProperties.cs b/MCGalaxy/Commands/World/CmdBlockProperties.cs index c86a0d252..a6950247a 100644 --- a/MCGalaxy/Commands/World/CmdBlockProperties.cs +++ b/MCGalaxy/Commands/World/CmdBlockProperties.cs @@ -34,17 +34,20 @@ namespace MCGalaxy.Commands.World { BlockProps[] scope = GetScope(p, args[0]); if (scope == null) return; - BlockID block = GetBlock(p, scope, args[1]); - if (block == Block.Invalid) return; + + Player pScope = scope == Block.Props ? null : p; + BlockID block = CommandParser.RawGetBlock(pScope, args[1]); + if (block == Block.Invalid) { + Player.Message(p, "&cThere is no block \"{0}\".", args[1]); return; + } string prop = args[2].ToLower(); SetProperty(p, scope, block, prop, args); } static BlockProps[] GetScope(Player p, string scope) { - if (scope.CaselessEq("core")) return Block.Props; - if (scope.CaselessEq("global")) return BlockDefinition.GlobalProps; - + if (scope.CaselessEq("core") || scope.CaselessEq("global")) return Block.Props; + if (scope.CaselessEq("level")) { if (Player.IsSuper(p)) { string src = p == null ? "console" : "IRC"; @@ -56,84 +59,47 @@ namespace MCGalaxy.Commands.World { return p.level.Props; } - Player.Message(p, "&cScope must \"core\", \"global\", or \"level\""); + Player.Message(p, "&cScope must be: core/global, or level"); return null; } - - static BlockID 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.Undefined(raw)) { - Player.Message(p, "&cThere is no block with id or name \"{0}\"", input); - return Block.Invalid; - } - return raw; - } 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 Block.Invalid; - } - return Block.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 Block.Invalid; - } - - if (p.level.CustomBlockDefs[raw] == BlockDefinition.GlobalDefs[raw]) { - Player.Message(p, "&cUse %T/BlockProps global &cto modify this custom block."); return Block.Invalid; - } - return Block.FromRaw((byte)raw); - } - } - - static int GetIndex(BlockProps[] scope, BlockID block) { - return scope == BlockDefinition.GlobalProps ? (BlockRaw)block : block; - } - + void SetProperty(Player p, BlockProps[] scope, BlockID block, string prop, string[] args) { - int i = GetIndex(scope, block); string text = args.Length > 3 ? args[3] : null; if (prop == "portal") { - Toggle(p, scope, block, "a portal", ref scope[i].IsPortal); + Toggle(p, scope, block, "a portal", ref scope[block].IsPortal); } else if (prop == "mb" || prop == "messageblock") { - Toggle(p, scope, block, "a message block", ref scope[i].IsMessageBlock); + Toggle(p, scope, block, "a message block", ref scope[block].IsMessageBlock); } else if (prop == "rails") { - Toggle(p, scope, block, "train rails", ref scope[i].IsRails); + Toggle(p, scope, block, "train rails", ref scope[block].IsRails); } else if (prop == "waterkills") { - Toggle(p, scope, block, "killed by water", ref scope[i].WaterKills); + Toggle(p, scope, block, "killed by water", ref scope[block].WaterKills); } else if (prop == "lavakills") { - Toggle(p, scope, block, "killed by lava", ref scope[i].LavaKills); + Toggle(p, scope, block, "killed by lava", ref scope[block].LavaKills); } else if (prop == "door") { - Toggle(p, scope, block, "a door", ref scope[i].IsDoor); + Toggle(p, scope, block, "a door", ref scope[block].IsDoor); } else if (prop == "tdoor") { - Toggle(p, scope, block, "a tdoor", ref scope[i].IsTDoor); + Toggle(p, scope, block, "a tdoor", ref scope[block].IsTDoor); } else if (prop == "killer" || prop == "death") { - Toggle(p, scope, block, "a killer block", ref scope[i].KillerBlock); + Toggle(p, scope, block, "a killer block", ref scope[block].KillerBlock); } else if (prop == "deathmsg" || prop == "deathmessage") { - SetDeathMessage(p, scope, block, i, text); + SetDeathMessage(p, scope, block, text); } else if (prop == "animalai" || prop == "animal") { - SetEnum(p, scope, block, i, text); + SetEnum(p, scope, block, text); } else if (prop == "stackid" || prop == "stackblock") { - SetStackId(p, scope, block, i, text); + SetStackId(p, scope, block, text); } else if (prop == "opblock" || prop == "op") { - Toggle(p, scope, block, "an OP block", ref scope[i].OPBlock); + Toggle(p, scope, block, "an OP block", ref scope[block].OPBlock); } else if (prop == "odoor") { - SetBlock(p, scope, block, i, text, ref scope[i].oDoorBlock, "oDoor"); + SetBlock(p, scope, block, text, ref scope[block].oDoorBlock, "oDoor"); } else if (prop == "grass") { - SetBlock(p, scope, block, i, text, ref scope[i].GrassBlock, "Grass form"); + SetBlock(p, scope, block, text, ref scope[block].GrassBlock, "Grass form"); } else if (prop == "dirt") { - SetBlock(p, scope, block, i, text, ref scope[i].DirtBlock, "Dirt form"); + SetBlock(p, scope, block, text, ref scope[block].DirtBlock, "Dirt form"); } else if (prop == "drownable" || prop == "drown") { - Toggle(p, scope, block, "drowns players", ref scope[i].Drownable); + Toggle(p, scope, block, "drowns players", ref scope[block].Drownable); } else { Help(p); } @@ -142,122 +108,84 @@ namespace MCGalaxy.Commands.World { static void Toggle(Player p, BlockProps[] scope, BlockID block, string type, ref bool on) { on = !on; - Level lvl = Player.IsSuper(p) ? null : p.level; - Player.Message(p, "Block {0} is {1}: {2}", - BlockName(scope, lvl, block), type, on ? "&aYes" : "&cNo"); - OnPropsChanged(scope, lvl, block); + + string blockName = BlockName(scope, p, block); + Player.Message(p, "Block {0} is {1}: {2}", blockName, type, on ? "&aYes" : "&cNo"); + OnPropsChanged(scope, p, block); } - static void SetEnum(Player p, BlockProps[] scope, BlockID block, int i, string msg) { - Level lvl = Player.IsSuper(p) ? null : p.level; + static void SetEnum(Player p, BlockProps[] scope, BlockID block, string msg) { AnimalAI ai = AnimalAI.None; if (!CommandParser.GetEnum(p, msg, "Animal AI", ref ai)) return; + scope[block].AnimalAI = ai; - scope[i].AnimalAI = ai; - Player.Message(p, "Animal AI for {0} set to: {1}", - BlockName(scope, lvl, block), ai); - OnPropsChanged(scope, lvl, block); + string blockName = BlockName(scope, p, block); + Player.Message(p, "Animal AI for {0} set to: {1}", blockName, ai); + OnPropsChanged(scope, p, block); } - static void SetDeathMessage(Player p, BlockProps[] scope, BlockID block, int i, string msg) { - scope[i].DeathMessage = msg; - Level lvl = Player.IsSuper(p) ? null : p.level; + static void SetDeathMessage(Player p, BlockProps[] scope, BlockID block, string msg) { + scope[block].DeathMessage = msg; + string blockName = BlockName(scope, p, block); if (msg == null) { - Player.Message(p, "Death message for {0} removed.", - BlockName(scope, lvl, block)); + Player.Message(p, "Death message for {0} removed.", blockName); } else { - Player.Message(p, "Death message for {0} set to: {1}", - BlockName(scope, lvl, block), msg); + Player.Message(p, "Death message for {0} set to: {1}", blockName, msg); } - OnPropsChanged(scope, lvl, block); + OnPropsChanged(scope, p, block); } - static void SetStackId(Player p, BlockProps[] scope, BlockID block, int i, string msg) { - Level lvl = Player.IsSuper(p) ? null : p.level; - + static void SetStackId(Player p, BlockProps[] scope, BlockID block, string msg) { BlockID stackBlock; if (msg == null) { stackBlock = Block.Air; } else { if (!CommandParser.GetBlock(p, msg, out stackBlock)) return; } - scope[i].StackBlock = stackBlock; + scope[block].StackBlock = stackBlock; + string blockName = BlockName(scope, p, block); if (stackBlock == Block.Air) { - Player.Message(p, "Removed stack block for {0}", BlockName(scope, lvl, block)); + Player.Message(p, "Removed stack block for {0}", blockName); } else { Player.Message(p, "Stack block for {0} set to: {1}", - BlockName(scope, lvl, block), Block.GetName(p, stackBlock)); + blockName, BlockName(scope, p, stackBlock)); } - OnPropsChanged(scope, lvl, block); + OnPropsChanged(scope, p, block); } - static void SetBlock(Player p, BlockProps[] scope, BlockID block, - int i, string msg, ref BlockID target, string type) { - Level lvl = Player.IsSuper(p) ? null : p.level; + static void SetBlock(Player p, BlockProps[] scope, BlockID block, + string msg, ref BlockID target, string type) { + string blockName = BlockName(scope, p, block); if (msg == null) { target = Block.Invalid; - Player.Message(p, "{1} for {0} removed.", BlockName(scope, lvl, block), type); + Player.Message(p, "{1} for {0} removed.", blockName, type); } else { BlockID other; if (!CommandParser.GetBlock(p, msg, out other)) return; if (other == block) { Player.Message(p, "ID of {0} must be different.", type); return; } - target = other; - Player.Message(p, "{2} for {0} set to: {1}", BlockName(scope, lvl, block), - BlockName(scope, lvl, other), type); + target = other; + Player.Message(p, "{2} for {0} set to: {1}", blockName, BlockName(scope, p, other), type); } - OnPropsChanged(scope, lvl, block); - } + OnPropsChanged(scope, p, block); + } - static void OnPropsChanged(BlockProps[] scope, Level level, BlockID block) { - scope[GetIndex(scope, block)].Changed = true; - BlockRaw raw = (BlockRaw)block; - + static void OnPropsChanged(BlockProps[] scope, Player p, BlockID block) { if (scope == Block.Props) { - BlockProps.Save("core", scope, Block.CorePropsLock, null); - Level[] loaded = LevelInfo.Loaded.Items; - if (!Block.IsPhysicsType(block)) { - BlockDefinition.GlobalProps[raw] = BlockDefinition.DefaultProps(block); - } - - foreach (Level lvl in loaded) { - if (lvl.HasCustomProps(block)) continue; - - lvl.Props[block] = BlockDefinition.DefaultProps(block); - lvl.UpdateBlockHandler(block); - } - } else if (scope == BlockDefinition.GlobalProps) { - Level[] loaded = LevelInfo.Loaded.Items; - BlockProps.Save("global", scope, BlockDefinition.GlobalPropsLock, null); - - foreach (Level lvl in loaded) { - if (lvl.CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw]) continue; - if (lvl.HasCustomProps(block)) continue; - - lvl.Props[block] = BlockDefinition.DefaultProps(block); - lvl.UpdateBlockHandler(block); - } + scope[block].ChangedScope |= 1; + BlockProps.Save("default", Block.Props, Block.PropsLock, 1); + Block.ChangeGlobalProps(block, scope[block]); } else { - BlockProps.Save("lvl_" + level.name, scope, level.PropsLock, idx => SelectLevel(level, idx)); - level.UpdateBlockHandler(block); + scope[block].ChangedScope |= 2; + BlockProps.Save("_" + p.level.name, scope, p.level.PropsLock, 2); + p.level.UpdateBlockHandler(block); } } - static bool SelectLevel(Level lvl, int i) { return lvl.HasCustomProps((BlockID)i); } - - static string BlockName(BlockProps[] scope, Level lvl, BlockID block) { - BlockRaw raw = (BlockRaw)block; - if (scope == Block.Props) return Block.coreNames[raw]; - BlockDefinition def = null; - - if (scope == BlockDefinition.GlobalProps) { - def = BlockDefinition.GlobalDefs[raw]; - } else { - def = lvl.CustomBlockDefs[raw]; - } - return def == null ? raw.ToString() : def.Name.Replace(" ", ""); + static string BlockName(BlockProps[] scope, Player p, BlockID block) { + return scope == Block.Props ? Block.GetName(null, block) : Block.GetName(p, block); } diff --git a/MCGalaxy/Commands/World/CmdOverseer.SubCommands.cs b/MCGalaxy/Commands/World/CmdOverseer.SubCommands.cs index bc68c5630..f2e46802b 100644 --- a/MCGalaxy/Commands/World/CmdOverseer.SubCommands.cs +++ b/MCGalaxy/Commands/World/CmdOverseer.SubCommands.cs @@ -225,7 +225,7 @@ namespace MCGalaxy.Commands.World { if (name.Length == 0) { Player.Message(p, "You need to provide a player name."); return; } AddBuildPlayer(p, name); } else if (cmd == "DEL") { - if (name.Length == 0) { Player.Message(p, "You need to provide a player name, or \"ALL\"."); return; } + if (name.Length == 0) { Player.Message(p, "You need to provide a player name."); return; } DeleteBuildPlayer(p, name); } else if (cmd == "BLOCK") { if (name.Length == 0) { Player.Message(p, "You need to provide a player name."); return; } diff --git a/MCGalaxy/Commands/building/CmdMessageBlock.cs b/MCGalaxy/Commands/building/CmdMessageBlock.cs index f2fc7ce8c..806f1945c 100644 --- a/MCGalaxy/Commands/building/CmdMessageBlock.cs +++ b/MCGalaxy/Commands/building/CmdMessageBlock.cs @@ -192,28 +192,21 @@ namespace MCGalaxy.Commands.Building { return Block.GetName(p, block); } - static void AllNames(Player p, List names) { - for (int i = 0; i < Block.ExtendedCount; i++) { - string name = Format((BlockID)i, p, p.level.Props); - if (name != null) names.Add(name); - } - } - - static void CoreNames(List names) { - for (int i = 0; i < Block.Count; i++) { - string name = Format((BlockID)i, null, Block.Props); + static List SupportedBlocks(Player p) { + List names = new List(); + BlockProps[] props = Player.IsSuper(p) ? Block.Props : p.level.Props; + + for (int i = 0; i < props.Length; i++) { + string name = Format((BlockID)i, p, props); if (name != null) names.Add(name); } + return names; } public override void Help(Player p) { Player.Message(p, "%T/MB [block] [message]"); Player.Message(p, "%HPlaces a message in your next block."); - - List names = new List(); - if (Player.IsSuper(p)) CoreNames(names); - else AllNames(p, names); - + List names = SupportedBlocks(p); 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."); diff --git a/MCGalaxy/Commands/building/CmdPortal.cs b/MCGalaxy/Commands/building/CmdPortal.cs index e93cc16ef..4ba55e59b 100644 --- a/MCGalaxy/Commands/building/CmdPortal.cs +++ b/MCGalaxy/Commands/building/CmdPortal.cs @@ -195,18 +195,15 @@ namespace MCGalaxy.Commands.Building { return Block.GetName(p, block); } - static void AllNames(Player p, List names) { - for (int i = 0; i < Block.ExtendedCount; i++) { - string name = Format((ushort)i, p, p.level.Props); - if (name != null) names.Add(name); - } - } - - static void CoreNames(List names) { - for (int i = 0; i < Block.Count; i++) { - string name = Format((ushort)i, null, Block.Props); + static List SupportedBlocks(Player p) { + List names = new List(); + BlockProps[] props = Player.IsSuper(p) ? Block.Props : p.level.Props; + + for (int i = 0; i < props.Length; i++) { + string name = Format((BlockID)i, p, props); if (name != null) names.Add(name); } + return names; } public override void Help(Player p) { @@ -215,11 +212,7 @@ 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."); Player.Message(p, "%H Note: The exit can be on a different level."); - - List names = new List(); - if (Player.IsSuper(p)) CoreNames(names); - else AllNames(p, names); - + List names = SupportedBlocks(p); 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 83ef7875d..c8534cbaf 100644 --- a/MCGalaxy/Levels/Level.cs +++ b/MCGalaxy/Levels/Level.cs @@ -444,6 +444,8 @@ namespace MCGalaxy { } internal bool HasCustomProps(BlockID block) { + if ((Props[block].ChangedScope & 2) != 0) return true; + if (Block.IsPhysicsType(block)) return false; BlockRaw raw = (BlockRaw)block; return CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw]; @@ -453,7 +455,7 @@ namespace MCGalaxy { for (int i = 0; i < Props.Length; i++) { BlockID block = (BlockID)i; if (!HasCustomProps(block)) { - Props[i] = BlockDefinition.DefaultProps(block); + Props[i] = Block.Props[i]; } else { Props[i] = BlockProps.MakeDefault(); } @@ -462,7 +464,14 @@ namespace MCGalaxy { public void UpdateBlockProps() { LoadCoreProps(); - BlockProps.Load("lvl_" + MapName, Props, PropsLock, true); + string propsPath = BlockProps.PropsPath("_" + MapName); + + // backwards compatibility with older versions + if (!File.Exists(propsPath)) { + BlockProps.Load("lvl_" + MapName, Props, PropsLock, 2, true); + } else { + BlockProps.Load("_" + MapName, Props, PropsLock, 2, false); + } } public void UpdateBlockHandlers() { diff --git a/MCGalaxy/Server/Server.cs b/MCGalaxy/Server/Server.cs index bca88f964..3b9eb7d24 100644 --- a/MCGalaxy/Server/Server.cs +++ b/MCGalaxy/Server/Server.cs @@ -201,7 +201,6 @@ namespace MCGalaxy { Command.InitAll(); CommandPerms.Load(); Block.SetBlocks(); - BlockDefinition.UpdateGlobalBlockProps(); Awards.Load(); Economy.Load(); WarpList.Global.Filename = "extra/warps.save";