diff --git a/MCGalaxy/Blocks/Block.Convert.cs b/MCGalaxy/Blocks/Block.Convert.cs index ff827e6b8..ea754ea0f 100644 --- a/MCGalaxy/Blocks/Block.Convert.cs +++ b/MCGalaxy/Blocks/Block.Convert.cs @@ -71,7 +71,7 @@ namespace MCGalaxy } public static string GetColoredName(Player p, BlockID block) { - BlockPerms perms = BlockPerms.Find(block); + BlockPerms perms = BlockPerms.GetPlace(block); // TODO check Delete perms too? return Group.GetColor(perms.MinRank) + Block.GetName(p, block); } diff --git a/MCGalaxy/Commands/CommandParser.cs b/MCGalaxy/Commands/CommandParser.cs index 782bb1cf2..0f8f537cc 100644 --- a/MCGalaxy/Commands/CommandParser.cs +++ b/MCGalaxy/Commands/CommandParser.cs @@ -222,8 +222,8 @@ namespace MCGalaxy.Commands /// Returns whether the player is allowed to place/modify/delete the given block. /// Outputs information of which ranks can modify the block if not. public static bool IsBlockAllowed(Player p, string action, BlockID block) { - if (p.group.Blocks[block]) return true; - BlockPerms.Find(block).MessageCannotUse(p, action); + if (p.group.CanPlace[block]) return true; + BlockPerms.GetPlace(block).MessageCannotUse(p, action); // TODO: Delete permissions too? return false; } diff --git a/MCGalaxy/Commands/Information/CmdBlocks.cs b/MCGalaxy/Commands/Information/CmdBlocks.cs index fdd51f277..adfa57170 100644 --- a/MCGalaxy/Commands/Information/CmdBlocks.cs +++ b/MCGalaxy/Commands/Information/CmdBlocks.cs @@ -52,7 +52,7 @@ namespace MCGalaxy.Commands.Info Group grp = Group.Find(type); p.Message("Blocks which {0} &Scan place: ", grp.ColoredName); OutputBlocks(p, type, modifier, - b => grp.Blocks[b]); + b => grp.CanPlace[b]); } else if (args.Length > 1) { Help(p); } else { diff --git a/MCGalaxy/Commands/Information/CmdHelp.cs b/MCGalaxy/Commands/Information/CmdHelp.cs index bdd589d42..c2fc2e1bc 100644 --- a/MCGalaxy/Commands/Information/CmdHelp.cs +++ b/MCGalaxy/Commands/Information/CmdHelp.cs @@ -136,7 +136,9 @@ namespace MCGalaxy.Commands.Info p.Message("Block \"{0}\" appears as &b{1}", message, Block.GetName(p, Block.Convert(block))); - BlockPerms.Find(block).MessageCannotUse(p, "use"); + + BlockPerms.GetPlace(block) .MessageCannotUse(p, "use"); + BlockPerms.GetDelete(block).MessageCannotUse(p, "delete"); DescribePhysics(p, message, block); return true; diff --git a/MCGalaxy/Commands/Moderation/CmdBlockSet.cs b/MCGalaxy/Commands/Moderation/CmdBlockSet.cs index 7b52f7c1b..c663cc22d 100644 --- a/MCGalaxy/Commands/Moderation/CmdBlockSet.cs +++ b/MCGalaxy/Commands/Moderation/CmdBlockSet.cs @@ -29,15 +29,19 @@ namespace MCGalaxy.Commands.Moderation { BlockID block; if (!CommandParser.GetBlockIfAllowed(p, args[0], "change permissions of", out block)) return; - BlockPerms perms = BlockPerms.Find(block); + // TODO rethink messaging + BlockPerms perms = BlockPerms.GetPlace(block); SetPerms(p, args, data, perms, "block"); } - protected override void UpdatePerms(ItemPerms perms, Player p, string msg) { + protected override void UpdatePerms(ItemPerms perms, Player p, string msg) { + BlockID block = ((BlockPerms)perms).ID; + + // TODO better solution + perms.CopyPermissionsTo(BlockPerms.GetDelete(block)); BlockPerms.Save(); BlockPerms.ApplyChanges(); - BlockID block = ((BlockPerms)perms).ID; if (!Block.IsPhysicsType(block)) { BlockPerms.ResendAllBlockPermissions(); } diff --git a/MCGalaxy/Commands/Moderation/ItemPermsCmd.cs b/MCGalaxy/Commands/Moderation/ItemPermsCmd.cs index d14411625..317bc16cf 100644 --- a/MCGalaxy/Commands/Moderation/ItemPermsCmd.cs +++ b/MCGalaxy/Commands/Moderation/ItemPermsCmd.cs @@ -17,8 +17,10 @@ */ using System.Collections.Generic; -namespace MCGalaxy.Commands.Moderation { - public abstract class ItemPermsCmd : Command2 { +namespace MCGalaxy.Commands.Moderation +{ + public abstract class ItemPermsCmd : Command2 + { public override string type { get { return CommandTypes.Moderation; } } public override LevelPermission defaultRank { get { return LevelPermission.Operator; } } diff --git a/MCGalaxy/Commands/building/CmdCopy.cs b/MCGalaxy/Commands/building/CmdCopy.cs index 679e16a07..d1db95753 100644 --- a/MCGalaxy/Commands/building/CmdCopy.cs +++ b/MCGalaxy/Commands/building/CmdCopy.cs @@ -139,7 +139,7 @@ namespace MCGalaxy.Commands.Building for (ushort x = minX; x <= maxX; ++x) { block = p.level.GetBlock(x, y, z); - if (!p.group.Blocks[block]) { index++; continue; } + if (!p.group.CanPlace[block]) { index++; continue; } if (block != Block.Air || cState.PasteAir) cState.UsedBlocks++; cState.Set(block, index); diff --git a/MCGalaxy/Config/Permissions/BlockPerms.cs b/MCGalaxy/Config/Permissions/BlockPerms.cs index 2486ae168..ed66ad329 100644 --- a/MCGalaxy/Config/Permissions/BlockPerms.cs +++ b/MCGalaxy/Config/Permissions/BlockPerms.cs @@ -28,7 +28,8 @@ namespace MCGalaxy.Blocks public BlockID ID; public override string ItemName { get { return ID.ToString(); } } - static BlockPerms[] List = new BlockPerms[Block.SUPPORTED_COUNT]; + static BlockPerms[] PlaceList = new BlockPerms[Block.SUPPORTED_COUNT]; + static BlockPerms[] DeleteList = new BlockPerms[Block.SUPPORTED_COUNT]; public BlockPerms(BlockID id, LevelPermission min) : base(min) { @@ -41,8 +42,8 @@ namespace MCGalaxy.Blocks } - /// Find the permissions for the given block. - public static BlockPerms Find(BlockID b) { return List[b]; } + public static BlockPerms GetPlace(BlockID b) { return PlaceList[b]; } + public static BlockPerms GetDelete(BlockID b) { return DeleteList[b]; } public static void ResendAllBlockPermissions() { @@ -67,10 +68,15 @@ namespace MCGalaxy.Blocks } static void SaveCore() { - using (StreamWriter w = new StreamWriter(Paths.BlockPermsFile)) { - WriteHeader(w, "block", "each block", "Block ID", "lava"); + SaveList(Paths.PlacePermsFile, PlaceList, "use"); + SaveList(Paths.DeletePermsFile, DeleteList, "delete"); + } + + static void SaveList(string path, BlockPerms[] list, string action) { + using (StreamWriter w = new StreamWriter(path)) { + WriteHeader(w, "block", "each block", "Block ID", "lava", action); - foreach (BlockPerms perms in List) + foreach (BlockPerms perms in list) { if (Block.Undefined(perms.ID)) continue; w.WriteLine(perms.Serialise()); @@ -88,9 +94,14 @@ namespace MCGalaxy.Blocks } public static void SetUsable(Group grp) { - foreach (BlockPerms perms in List) + SetUsableList(PlaceList, grp.CanPlace, grp); + SetUsableList(DeleteList, grp.CanDelete, grp); + } + + static void SetUsableList(BlockPerms[] list, bool[] permsList, Group grp) { + foreach (BlockPerms perms in list) { - grp.Blocks[perms.ID] = perms.UsableBy(grp.Permission); + permsList[perms.ID] = perms.UsableBy(grp.Permission); } } @@ -103,14 +114,33 @@ namespace MCGalaxy.Blocks static void LoadCore() { SetDefaultPerms(); - if (!File.Exists(Paths.BlockPermsFile)) { Save(); return; } + bool placeExists = File.Exists(Paths.PlacePermsFile); + bool deleteExists = File.Exists(Paths.DeletePermsFile); - using (StreamReader r = new StreamReader(Paths.BlockPermsFile)) { - ProcessLines(r); + if (placeExists) LoadFile(Paths.PlacePermsFile, PlaceList); + if (deleteExists) LoadFile(Paths.DeletePermsFile, DeleteList); + if (placeExists || deleteExists) return; + + if (File.Exists(Paths.BlockPermsFile)) { + LoadFile(Paths.BlockPermsFile, PlaceList); + + // TODO proper migration + for (int i = 0; i < Block.SUPPORTED_COUNT; i++) + PlaceList[i].CopyPermissionsTo(DeleteList[i]); + SetDefaultSpecialDeletePerms(); + + File.Move(Paths.BlockPermsFile, Paths.BlockPermsFile + ".bak"); + } + Save(); + } + + static void LoadFile(string path, BlockPerms[] list) { + using (StreamReader r = new StreamReader(path)) { + ProcessLines(r, list); } } - static void ProcessLines(StreamReader r) { + static void ProcessLines(StreamReader r, BlockPerms[] list) { string[] args = new string[4]; string line; @@ -131,7 +161,7 @@ namespace MCGalaxy.Blocks List allowed, disallowed; Deserialise(args, 1, out min, out allowed, out disallowed); - Set(block, min, allowed, disallowed); + Set(block, min, list, allowed, disallowed); } catch { Logger.Log(LogType.Warning, "Hit an error on the block " + line); continue; @@ -139,19 +169,20 @@ namespace MCGalaxy.Blocks } } - static void Set(BlockID b, LevelPermission min, + static void Set(BlockID b, LevelPermission min, BlockPerms[] list, List allowed, List disallowed) { - BlockPerms perms = List[b]; + BlockPerms perms = list[b]; if (perms == null) { perms = new BlockPerms(b, min); - List[b] = perms; + list[b] = perms; } perms.Init(min, allowed, disallowed); } - + static void SetDefaultPerms() { - for (BlockID block = 0; block < Block.SUPPORTED_COUNT; block++) { + for (BlockID block = 0; block < Block.SUPPORTED_COUNT; block++) + { BlockProps props = Block.Props[block]; LevelPermission min; @@ -167,8 +198,15 @@ namespace MCGalaxy.Blocks min = DefaultPerm(block); } - Set(block, min, null, null); + Set(block, min, PlaceList, null, null); + Set(block, min, DeleteList, null, null); } + SetDefaultSpecialDeletePerms(); + } + + static void SetDefaultSpecialDeletePerms() { + for (BlockID b = Block.Water; b <= Block.StillLava; b++) + DeleteList[b].MinRank = LevelPermission.Guest; } static LevelPermission DefaultPerm(BlockID block) { diff --git a/MCGalaxy/Config/Permissions/CommandExtraPerms.cs b/MCGalaxy/Config/Permissions/CommandExtraPerms.cs index 15e228753..ee9189269 100644 --- a/MCGalaxy/Config/Permissions/CommandExtraPerms.cs +++ b/MCGalaxy/Config/Permissions/CommandExtraPerms.cs @@ -88,7 +88,7 @@ namespace MCGalaxy.Commands static void SaveCore() { using (StreamWriter w = new StreamWriter(Paths.CmdExtraPermsFile)) { WriteHeader(w, "extra command permissions", "extra permissions in some commands", - "CommandName:ExtraPermissionNumber", "countdown:1"); + "CommandName:ExtraPermissionNumber", "countdown:1", "use"); foreach (CommandExtraPerms perms in list) { w.WriteLine(perms.Serialise()); diff --git a/MCGalaxy/Config/Permissions/CommandPerms.cs b/MCGalaxy/Config/Permissions/CommandPerms.cs index 85ee39706..f45aa98e9 100644 --- a/MCGalaxy/Config/Permissions/CommandPerms.cs +++ b/MCGalaxy/Config/Permissions/CommandPerms.cs @@ -77,7 +77,7 @@ namespace MCGalaxy.Commands static void SaveCore() { using (StreamWriter w = new StreamWriter(Paths.CmdPermsFile)) { - WriteHeader(w, "command", "each command", "CommandName", "gun"); + WriteHeader(w, "command", "each command", "CommandName", "gun", "use"); foreach (CommandPerms perms in List) { diff --git a/MCGalaxy/Config/Permissions/ItemPerms.cs b/MCGalaxy/Config/Permissions/ItemPerms.cs index 2fb521d23..b88a43b7e 100644 --- a/MCGalaxy/Config/Permissions/ItemPerms.cs +++ b/MCGalaxy/Config/Permissions/ItemPerms.cs @@ -99,13 +99,13 @@ namespace MCGalaxy protected static void WriteHeader(StreamWriter w, string itemName, string itemDesc, - string headerName, string headerExample) { + string headerName, string headerExample, string action) { w.WriteLine("#Version 2"); - w.WriteLine("# This file contains the permissions to use {0}", itemDesc); + w.WriteLine("# This file contains the permissions to {1} {0}", itemDesc, action); w.WriteLine("# How permissions work:"); - w.WriteLine("# - If the player's rank is in Disallowed, they cannot use the {0}", itemName); - w.WriteLine("# - Otherwise if the player's rank is in Allowed, they can use the {0}", itemName); - w.WriteLine("# - Otherwise if the player's rank is >= Lowest Rank, they can use the {0}", itemName); + w.WriteLine("# - If the player's rank is in Disallowed, they cannot {1} the {0}", itemName, action); + w.WriteLine("# - Otherwise if the player's rank is in Allowed, they can {1} the {0}", itemName, action); + w.WriteLine("# - Otherwise if the player's rank is >= Lowest Rank, they can {1} the {0}", itemName, action); w.WriteLine("#"); w.WriteLine("# Layout: {0} : LowestRank : Disallowed : Allowed", headerName); w.WriteLine("# e.g. {0} : 60 : 80,67 : 40,41,55", headerExample); diff --git a/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs b/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs index 865e71db5..575e51134 100644 --- a/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs +++ b/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs @@ -160,7 +160,7 @@ namespace MCGalaxy.Drawing.Ops #endif // Check to make sure the block is actually different and that can be used - if (old == b.Block || !p.group.Blocks[old] || !p.group.Blocks[b.Block]) return; + if (old == b.Block || !p.group.CanDelete[old] || !p.group.CanPlace[b.Block]) return; // Check if player can affect block at coords in world AccessController denier = lvl.CanAffect(p, b.X, b.Y, b.Z); diff --git a/MCGalaxy/Levels/Level.Blocks.cs b/MCGalaxy/Levels/Level.Blocks.cs index 53f6f80f8..9f5855ff9 100644 --- a/MCGalaxy/Levels/Level.Blocks.cs +++ b/MCGalaxy/Levels/Level.Blocks.cs @@ -220,13 +220,7 @@ namespace MCGalaxy { blocks[index] = (BlockRaw)block; } } - - - internal bool BuildIn(BlockID block) { - if (block == Block.Op_Water || block == Block.Op_Lava || Props[block].IsPortal || Props[block].IsMessageBlock) return false; - block = Block.Convert(block); - return block >= Block.Water && block <= Block.StillLava; - } + /// Returns the AccessController denying the player from changing blocks at the given coordinates. /// If no AccessController denies the player, returns null. @@ -265,7 +259,7 @@ namespace MCGalaxy { } public bool CheckAffect(Player p, ushort x, ushort y, ushort z, BlockID old, BlockID block) { - if (!p.group.Blocks[old] || !p.group.Blocks[block]) return false; + if (!p.group.CanDelete[old] || !p.group.CanPlace[block]) return false; AccessController denier = CanAffect(p, x, y, z); if (denier == null) return true; diff --git a/MCGalaxy/Network/Player.Networking.cs b/MCGalaxy/Network/Player.Networking.cs index 968ed3a88..386930246 100644 --- a/MCGalaxy/Network/Player.Networking.cs +++ b/MCGalaxy/Network/Player.Networking.cs @@ -205,13 +205,14 @@ namespace MCGalaxy int size = extBlocks ? 5 : 4; byte[] bulk = new byte[count * size]; - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { BlockID block = Block.FromRaw((BlockID)i); - bool place = group.Blocks[block] && level.CanPlace; + bool place = group.CanPlace[block] && level.CanPlace; // NOTE: If you can't delete air, then you're no longer able to place blocks // (see ClassiCube client #815) // TODO: Maybe better solution than this? - bool delete = group.Blocks[block] && (level.CanDelete || i == Block.Air); + bool delete = group.CanDelete[block] && (level.CanDelete || i == Block.Air); // Placing air is the same as deleting existing block at that position in the world if (block == Block.Air) place &= delete; diff --git a/MCGalaxy/Player/Group.cs b/MCGalaxy/Player/Group.cs index 62e5ecdb7..cfe296024 100644 --- a/MCGalaxy/Player/Group.cs +++ b/MCGalaxy/Player/Group.cs @@ -69,7 +69,8 @@ namespace MCGalaxy internal string filename; public PlayerList Players; - public bool[] Blocks = new bool[Block.SUPPORTED_COUNT]; + public bool[] CanPlace = new bool[Block.SUPPORTED_COUNT]; + public bool[] CanDelete = new bool[Block.SUPPORTED_COUNT]; public Group() { } private Group(LevelPermission perm, int drawLimit, int undoMins, string name, string color, int volume, int realms) { @@ -100,7 +101,8 @@ namespace MCGalaxy public static Group Find(string name) { MapName(ref name); - foreach (Group grp in GroupList) { + foreach (Group grp in GroupList) + { if (grp.Name.CaselessEq(name)) return grp; } return null; diff --git a/MCGalaxy/Player/Player.Handlers.cs b/MCGalaxy/Player/Player.Handlers.cs index b3e267eea..aa33f799f 100644 --- a/MCGalaxy/Player/Player.Handlers.cs +++ b/MCGalaxy/Player/Player.Handlers.cs @@ -132,9 +132,9 @@ namespace MCGalaxy } internal bool CheckManualChange(BlockID old, bool deleteMode) { - if (!group.Blocks[old] && !level.BuildIn(old) && !Block.AllowBreak(old)) { + if (!group.CanDelete[old] && !Block.AllowBreak(old)) { string action = deleteMode ? "delete" : "replace"; - BlockPerms.Find(old).MessageCannotUse(this, action); + BlockPerms.GetDelete(old).MessageCannotUse(this, action); return false; } return true; diff --git a/MCGalaxy/Player/Player.cs b/MCGalaxy/Player/Player.cs index 5f79003ca..d392b47f8 100644 --- a/MCGalaxy/Player/Player.cs +++ b/MCGalaxy/Player/Player.cs @@ -331,7 +331,7 @@ namespace MCGalaxy { public const string USERNAME_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890._"; - internal byte UserType() { return group.Blocks[Block.Bedrock] ? (byte)100 : (byte)0; } + internal byte UserType() { return group.CanPlace[Block.Bedrock] ? (byte)100 : (byte)0; } #endregion diff --git a/MCGalaxy/Server/Paths.cs b/MCGalaxy/Server/Paths.cs index 2cbef0bee..71e63a62c 100644 --- a/MCGalaxy/Server/Paths.cs +++ b/MCGalaxy/Server/Paths.cs @@ -38,7 +38,10 @@ namespace MCGalaxy public const string JokerFile = "text/joker.txt"; public const string EightBallFile = "text/8ball.txt"; - public const string BlockPermsFile = "properties/block.properties"; + public const string BlockPermsFile = "properties/block.properties"; + public const string PlacePermsFile = "properties/place.properties"; + public const string DeletePermsFile = "properties/delete.properties"; + public const string CmdPermsFile = "properties/command.properties"; public const string CmdExtraPermsFile = "properties/ExtraCommandPermissions.properties"; public const string EconomyPropsFile = "properties/economy.properties";