Merge pull request #787 from UnknownShadow200/PlaceDeletePermissions

Split up Block permissions into Place and Delete permissions
This commit is contained in:
UnknownShadow200 2023-12-26 10:30:59 +11:00 committed by GitHub
commit ffab090303
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 217 additions and 111 deletions

View File

@ -30,13 +30,14 @@ namespace MCGalaxy.Gui {
// need to keep a list of changed block perms, because we don't want // 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' // to modify the server's live permissions if user clicks 'discard'
BlockPerms blockPermsOrig, blockPermsCopy; BlockPerms placePermsOrig, placePermsCopy;
List<BlockPerms> blockPermsChanged = new List<BlockPerms>(); List<BlockPerms> placePermsChanged = new List<BlockPerms>();
BlockProps[] blockPropsChanged = new BlockProps[Block.Props.Length]; BlockProps[] blockPropsChanged = new BlockProps[Block.Props.Length];
// TODO delete permissions too
void LoadBlocks() { void LoadBlocks() {
blk_list.Items.Clear(); blk_list.Items.Clear();
blockPermsChanged.Clear(); placePermsChanged.Clear();
blockIDMap = new List<BlockID>(); blockIDMap = new List<BlockID>();
for (int b = 0; b < blockPropsChanged.Length; b++) for (int b = 0; b < blockPropsChanged.Length; b++)
@ -59,7 +60,7 @@ namespace MCGalaxy.Gui {
} }
void SaveBlocks() { void SaveBlocks() {
if (blockPermsChanged.Count > 0) if (placePermsChanged.Count > 0)
SaveBlockPermissions(); SaveBlockPermissions();
if (AnyBlockPropsChanged()) if (AnyBlockPropsChanged())
SaveBlockProps(); SaveBlockProps();
@ -68,10 +69,13 @@ namespace MCGalaxy.Gui {
} }
void SaveBlockPermissions() { void SaveBlockPermissions() {
foreach (BlockPerms changed in blockPermsChanged) foreach (BlockPerms changed in placePermsChanged)
{ {
BlockPerms orig = BlockPerms.Find(changed.ID); BlockPerms pOrig = BlockPerms.GetPlace(changed.ID);
changed.CopyPermissionsTo(orig); changed.CopyPermissionsTo(pOrig);
BlockPerms dOrig = BlockPerms.GetDelete(changed.ID);
changed.CopyPermissionsTo(dOrig);
} }
BlockPerms.Save(); BlockPerms.Save();
@ -101,8 +105,9 @@ namespace MCGalaxy.Gui {
void blk_list_SelectedIndexChanged(object sender, EventArgs e) { void blk_list_SelectedIndexChanged(object sender, EventArgs e) {
curBlock = blockIDMap[blk_list.SelectedIndex]; curBlock = blockIDMap[blk_list.SelectedIndex];
blockPermsOrig = BlockPerms.Find(curBlock); placePermsOrig = BlockPerms.GetPlace(curBlock);
blockPermsCopy = blockPermsChanged.Find(p => p.ID == curBlock); placePermsCopy = placePermsChanged.Find(p => p.ID == curBlock);
BlockInitSpecificArrays(); BlockInitSpecificArrays();
blockItems.SupressEvents = true; blockItems.SupressEvents = true;
@ -119,7 +124,7 @@ namespace MCGalaxy.Gui {
blk_cbLava.Checked = props.LavaKills; blk_cbLava.Checked = props.LavaKills;
blk_cbWater.Checked = props.WaterKills; blk_cbWater.Checked = props.WaterKills;
BlockPerms perms = blockPermsCopy != null ? blockPermsCopy : blockPermsOrig; BlockPerms perms = placePermsCopy != null ? placePermsCopy : placePermsOrig;
blockItems.Update(perms); blockItems.Update(perms);
} }
@ -132,10 +137,10 @@ namespace MCGalaxy.Gui {
} }
ItemPerms BlockGetOrAddPermsChanged() { ItemPerms BlockGetOrAddPermsChanged() {
if (blockPermsCopy != null) return blockPermsCopy; if (placePermsCopy != null) return placePermsCopy;
blockPermsCopy = blockPermsOrig.Copy(); placePermsCopy = placePermsOrig.Copy();
blockPermsChanged.Add(blockPermsCopy); placePermsChanged.Add(placePermsCopy);
return blockPermsCopy; return placePermsCopy;
} }

View File

@ -71,7 +71,7 @@ namespace MCGalaxy
} }
public static string GetColoredName(Player p, BlockID block) { 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); return Group.GetColor(perms.MinRank) + Block.GetName(p, block);
} }

View File

@ -222,8 +222,8 @@ namespace MCGalaxy.Commands
/// <summary> Returns whether the player is allowed to place/modify/delete the given block. </summary> /// <summary> Returns whether the player is allowed to place/modify/delete the given block. </summary>
/// <remarks> Outputs information of which ranks can modify the block if not. </remarks> /// <remarks> Outputs information of which ranks can modify the block if not. </remarks>
public static bool IsBlockAllowed(Player p, string action, BlockID block) { public static bool IsBlockAllowed(Player p, string action, BlockID block) {
if (p.group.Blocks[block]) return true; if (p.group.CanPlace[block]) return true;
BlockPerms.Find(block).MessageCannotUse(p, action); BlockPerms.GetPlace(block).MessageCannotUse(p, action); // TODO: Delete permissions too?
return false; return false;
} }

View File

@ -52,7 +52,7 @@ namespace MCGalaxy.Commands.Info
Group grp = Group.Find(type); Group grp = Group.Find(type);
p.Message("Blocks which {0} &Scan place: ", grp.ColoredName); p.Message("Blocks which {0} &Scan place: ", grp.ColoredName);
OutputBlocks(p, type, modifier, OutputBlocks(p, type, modifier,
b => grp.Blocks[b]); b => grp.CanPlace[b]);
} else if (args.Length > 1) { } else if (args.Length > 1) {
Help(p); Help(p);
} else { } else {

View File

@ -136,7 +136,9 @@ namespace MCGalaxy.Commands.Info
p.Message("Block \"{0}\" appears as &b{1}", p.Message("Block \"{0}\" appears as &b{1}",
message, Block.GetName(p, Block.Convert(block))); 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); DescribePhysics(p, message, block);
return true; return true;

View File

@ -14,46 +14,86 @@
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the Licenses for the specific language governing or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses. permissions and limitations under the Licenses.
*/ */
using MCGalaxy.Blocks; using MCGalaxy.Blocks;
using BlockID = System.UInt16; using BlockID = System.UInt16;
namespace MCGalaxy.Commands.Moderation { namespace MCGalaxy.Commands.Moderation
public sealed class CmdBlockSet : ItemPermsCmd { {
public sealed class CmdBlockSet : ItemPermsCmd
{
public override string name { get { return "BlockSet"; } } public override string name { get { return "BlockSet"; } }
public override void Use(Player p, string message, CommandData data) { public override void Use(Player p, string message, CommandData data) {
bool canPlace = true; const string PLACE_PREFIX = "place ";
bool canDelete = true; const string DELETE_PREFIX = "delete ";
string placeMsg = null, deleteMsg = null;
if (message.CaselessStarts(PLACE_PREFIX)) {
canDelete = false;
message = message.Substring(PLACE_PREFIX.Length);
} else if (message.CaselessStarts(DELETE_PREFIX)) {
canPlace = false;
message = message.Substring(DELETE_PREFIX.Length);
}
string[] args = message.SplitSpaces(2); string[] args = message.SplitSpaces(2);
if (args.Length < 2) { Help(p); return; } if (args.Length < 2) { Help(p); return; }
BlockID block; BlockID block;
if (!CommandParser.GetBlockIfAllowed(p, args[0], "change permissions of", out block)) return; if (!CommandParser.GetBlockIfAllowed(p, args[0], "change permissions of", out block)) return;
BlockPerms perms = BlockPerms.Find(block); // TODO avoid showing message twice
SetPerms(p, args, data, perms, "block"); if (canPlace) {
BlockPerms perms = BlockPerms.GetPlace(block);
placeMsg = SetPerms(p, args, data, perms, "block", "use", "usable");
}
if (canDelete) {
BlockPerms perms = BlockPerms.GetDelete(block);
deleteMsg = SetPerms(p, args, data, perms, "block", "delete", "deletable");
}
if (placeMsg == null && deleteMsg == null) return;
UpdatePerms(block, p, placeMsg, deleteMsg);
} }
protected override void UpdatePerms(ItemPerms perms, Player p, string msg) { void UpdatePerms(BlockID block, Player p, string placeMsg, string deleteMsg) {
BlockPerms.Save(); BlockPerms.Save();
BlockPerms.ApplyChanges(); BlockPerms.ApplyChanges();
BlockID block = ((BlockPerms)perms).ID;
if (!Block.IsPhysicsType(block)) { if (!Block.IsPhysicsType(block)) {
BlockPerms.ResendAllBlockPermissions(); BlockPerms.ResendAllBlockPermissions();
} }
string name = Block.GetName(p, block); string name = Block.GetName(p, block);
Announce(p, name + msg);
if (placeMsg != null && deleteMsg != null) {
Announce(p, name + placeMsg.Replace("usable", "usable and deletable"));
} else if (placeMsg != null) {
Announce(p, name + placeMsg);
} else {
Announce(p, name + deleteMsg);
}
} }
public override void Help(Player p) { public override void Help(Player p) {
p.Message("&T/BlockSet [block] [rank]"); p.Message("&T/BlockSet [block] [rank]");
p.Message("&HSets lowest rank that can modify/use [block] to [rank]"); p.Message("&HSets lowest rank that can use and delete [block] to [rank]");
p.Message("&T/BlockSet place [block] [rank]");
p.Message("&HSets lowest rank that can use/modify [block] to [rank]");
p.Message("&T/BlockSet delete [block] [rank]");
p.Message("&HSets lowest rank that can delete [block] to [rank]");
p.Message("&H- For more advanced permissions, see &T/Help blockset advanced");
p.Message("&H- To see available ranks, type &T/ViewRanks");
}
public override void Help(Player p, string message) {
if (!message.CaselessEq("advanced")) { base.Help(p, message); return; }
p.Message("&T/BlockSet [block] +[rank]"); p.Message("&T/BlockSet [block] +[rank]");
p.Message("&HAllows a specific rank to modify/use [block]"); p.Message("&HAllows a specific rank to use and delete [block]");
p.Message("&T/BlockSet [block] -[rank]"); p.Message("&T/BlockSet [block] -[rank]");
p.Message("&HPrevents a specific rank from modifying/using [block]"); p.Message("&HPrevents a specific rank from using or deleting [block]");
p.Message("&HTo see available ranks, type &T/ViewRanks"); // TODO place and delete messages
} }
} }
} }

View File

@ -15,15 +15,17 @@
or implied. See the Licenses for the specific language governing or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses. permissions and limitations under the Licenses.
*/ */
namespace MCGalaxy.Commands.Moderation { namespace MCGalaxy.Commands.Moderation
public sealed class CmdCmdSet : ItemPermsCmd { {
public sealed class CmdCmdSet : ItemPermsCmd
{
public override string name { get { return "CmdSet"; } } public override string name { get { return "CmdSet"; } }
public override void Use(Player p, string message, CommandData data) { public override void Use(Player p, string message, CommandData data) {
string[] args = message.SplitSpaces(3); string[] args = message.SplitSpaces(3);
if (args.Length < 2) { Help(p); return; } if (args.Length < 2) { Help(p); return; }
string cmdName = args[0], cmdArgs = ""; string cmdName = args[0], cmdArgs = "", msg;
Command.Search(ref cmdName, ref cmdArgs); Command.Search(ref cmdName, ref cmdArgs);
Command cmd = Command.Find(cmdName); Command cmd = Command.Find(cmdName);
@ -35,8 +37,11 @@ namespace MCGalaxy.Commands.Moderation {
} }
if (args.Length == 2) { if (args.Length == 2) {
SetPerms(p, args, data, cmd.Permissions, "command"); msg = SetPerms(p, args, data, cmd.Permissions, "command", "use", "usable");
if (msg != null)
UpdateCommandPerms(cmd.Permissions, p, msg);
} else { } else {
int num = 0; int num = 0;
if (!CommandParser.GetInt(p, args[2], "Extra permission number", ref num)) return; if (!CommandParser.GetInt(p, args[2], "Extra permission number", ref num)) return;
@ -44,33 +49,41 @@ namespace MCGalaxy.Commands.Moderation {
if (perms == null) { if (perms == null) {
p.Message("This command has no extra permission by that number."); return; p.Message("This command has no extra permission by that number."); return;
} }
SetPerms(p, args, data, perms, "extra permission");
msg = SetPerms(p, args, data, perms, "extra permission", "use", "usable");
if (msg != null)
UpdateExtraPerms(perms, p, msg);
} }
} }
protected override void UpdatePerms(ItemPerms perms, Player p, string msg) { void UpdateCommandPerms(ItemPerms perms, Player p, string msg) {
if (perms is CommandPerms) { CommandPerms.Save();
CommandPerms.Save(); CommandPerms.ApplyChanges();
CommandPerms.ApplyChanges(); Announce(p, perms.ItemName + msg);
Announce(p, perms.ItemName + msg); }
} else {
CommandExtraPerms.Save(); void UpdateExtraPerms(CommandExtraPerms perms, Player p, string msg) {
CommandExtraPerms ex = (CommandExtraPerms)perms; CommandExtraPerms.Save();
//Announce(p, cmd.name + "&S's extra permission " + idx + " was set to " + grp.ColoredName); //Announce(p, cmd.name + "&S's extra permission " + idx + " was set to " + grp.ColoredName);
Announce(p, ex.CmdName + " extra permission #" + ex.Num + msg); Announce(p, perms.CmdName + " extra permission #" + perms.Num + msg);
}
} }
public override void Help(Player p) { public override void Help(Player p) {
p.Message("&T/CmdSet [cmd] [rank]"); p.Message("&T/CmdSet [cmd] [rank]");
p.Message("&HSets lowest rank that can use [cmd] to [rank]"); p.Message("&HSets lowest rank that can use [cmd] to [rank]");
p.Message("&T/CmdSet [cmd] [rank] [extra permission number]");
p.Message("&HSet the lowest rank that has that extra permission for [cmd]");
p.Message("&H- For more advanced permissions, see &T/Help cmdset advanced");
p.Message("&H- To see available ranks, type &T/ViewRanks");
}
public override void Help(Player p, string message) {
if (!message.CaselessEq("advanced")) { base.Help(p, message); return; }
p.Message("&T/CmdSet [cmd] +[rank]"); p.Message("&T/CmdSet [cmd] +[rank]");
p.Message("&HAllows a specific rank to use [cmd]"); p.Message("&HAllows a specific rank to use [cmd]");
p.Message("&T/CmdSet [cmd] -[rank]"); p.Message("&T/CmdSet [cmd] -[rank]");
p.Message("&HPrevents a specific rank from using [cmd]"); p.Message("&HPrevents a specific rank from using [cmd]");
p.Message("&T/CmdSet [cmd] [rank] [extra permission number]");
p.Message("&HSet the lowest rank that has that extra permission for [cmd]");
p.Message("&HTo see available ranks, type &T/ViewRanks");
} }
} }
} }

View File

@ -17,44 +17,45 @@
*/ */
using System.Collections.Generic; using System.Collections.Generic;
namespace MCGalaxy.Commands.Moderation { namespace MCGalaxy.Commands.Moderation
public abstract class ItemPermsCmd : Command2 { {
public abstract class ItemPermsCmd : Command2
{
public override string type { get { return CommandTypes.Moderation; } } public override string type { get { return CommandTypes.Moderation; } }
public override LevelPermission defaultRank { get { return LevelPermission.Operator; } } public override LevelPermission defaultRank { get { return LevelPermission.Operator; } }
protected void SetPerms(Player p, string[] args, CommandData data, ItemPerms perms, string type) { protected string SetPerms(Player p, string[] args, CommandData data, ItemPerms perms, string type,
string actionNoun, string actionAdjective) {
string grpName = args[1]; string grpName = args[1];
if (!perms.UsableBy(data.Rank)) { if (!perms.UsableBy(data.Rank)) {
p.Message("You rank cannot use this {0}.", type); return; p.Message("You rank cannot {1} this {0}.", type, actionNoun); return null;
} }
if (grpName[0] == '+') { if (grpName[0] == '+') {
Group grp = GetGroup(p, data, grpName.Substring(1)); Group grp = GetGroup(p, data, grpName.Substring(1));
if (grp == null) return; if (grp == null) return null;
perms.Allow(grp.Permission); perms.Allow(grp.Permission);
UpdatePerms(perms, p, " &Scan now be used by " + grp.ColoredName); return " &Sis now " + actionAdjective + " by " + grp.ColoredName;
} else if (grpName[0] == '-') { } else if (grpName[0] == '-') {
Group grp = GetGroup(p, data, grpName.Substring(1)); Group grp = GetGroup(p, data, grpName.Substring(1));
if (grp == null) return; if (grp == null) return null;
if (data.Rank == grp.Permission) { if (data.Rank == grp.Permission) {
p.Message("You cannot disallow your own rank from using a {0}.", type); return; p.Message("&WCannot deny permissions for your own rank"); return null;
} }
perms.Disallow(grp.Permission); perms.Disallow(grp.Permission);
UpdatePerms(perms, p, " &Sis no longer usable by " + grp.ColoredName); return " &Sis no longer " + actionAdjective + " by " + grp.ColoredName;
} else { } else {
Group grp = GetGroup(p, data, grpName); Group grp = GetGroup(p, data, grpName);
if (grp == null) return; if (grp == null) return null;
perms.MinRank = grp.Permission; perms.MinRank = grp.Permission;
UpdatePerms(perms, p, " &Sis now usable by " + grp.ColoredName + "&S+"); return " &Sis now " + actionAdjective + " by " + grp.ColoredName + "&S+";
} }
} }
protected abstract void UpdatePerms(ItemPerms perms, Player p, string msg);
protected static Group GetGroup(Player p, CommandData data, string grpName) { protected static Group GetGroup(Player p, CommandData data, string grpName) {
Group grp = Matcher.FindRanks(p, grpName); Group grp = Matcher.FindRanks(p, grpName);
if (grp == null) return null; if (grp == null) return null;

View File

@ -139,7 +139,7 @@ namespace MCGalaxy.Commands.Building
for (ushort x = minX; x <= maxX; ++x) for (ushort x = minX; x <= maxX; ++x)
{ {
block = p.level.GetBlock(x, y, z); 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++; if (block != Block.Air || cState.PasteAir) cState.UsedBlocks++;
cState.Set(block, index); cState.Set(block, index);

View File

@ -28,7 +28,8 @@ namespace MCGalaxy.Blocks
public BlockID ID; public BlockID ID;
public override string ItemName { get { return ID.ToString(); } } 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) { public BlockPerms(BlockID id, LevelPermission min) : base(min) {
@ -41,8 +42,8 @@ namespace MCGalaxy.Blocks
} }
/// <summary> Find the permissions for the given block. </summary> public static BlockPerms GetPlace(BlockID b) { return PlaceList[b]; }
public static BlockPerms Find(BlockID b) { return List[b]; } public static BlockPerms GetDelete(BlockID b) { return DeleteList[b]; }
public static void ResendAllBlockPermissions() { public static void ResendAllBlockPermissions() {
@ -67,10 +68,15 @@ namespace MCGalaxy.Blocks
} }
static void SaveCore() { static void SaveCore() {
using (StreamWriter w = new StreamWriter(Paths.BlockPermsFile)) { SaveList(Paths.PlacePermsFile, PlaceList, "use");
WriteHeader(w, "block", "each block", "Block ID", "lava"); 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; if (Block.Undefined(perms.ID)) continue;
w.WriteLine(perms.Serialise()); w.WriteLine(perms.Serialise());
@ -88,9 +94,14 @@ namespace MCGalaxy.Blocks
} }
public static void SetUsable(Group grp) { 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,36 @@ namespace MCGalaxy.Blocks
static void LoadCore() { static void LoadCore() {
SetDefaultPerms(); 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)) { if (placeExists) LoadFile(Paths.PlacePermsFile, PlaceList);
ProcessLines(r); if (deleteExists) LoadFile(Paths.DeletePermsFile, DeleteList);
if (placeExists || deleteExists) return;
if (File.Exists(Paths.BlockPermsFile)) {
LoadFile(Paths.BlockPermsFile, PlaceList);
for (int i = 0; i < Block.SUPPORTED_COUNT; i++)
PlaceList[i].CopyPermissionsTo(DeleteList[i]);
SetDefaultSpecialDeletePerms();
try {
File.Move(Paths.BlockPermsFile, Paths.BlockPermsFile + ".bak");
} catch (Exception ex) {
Logger.LogError("Moving old block.properties file", ex);
}
}
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[] args = new string[4];
string line; string line;
@ -131,7 +164,7 @@ namespace MCGalaxy.Blocks
List<LevelPermission> allowed, disallowed; List<LevelPermission> allowed, disallowed;
Deserialise(args, 1, out min, out allowed, out disallowed); Deserialise(args, 1, out min, out allowed, out disallowed);
Set(block, min, allowed, disallowed); Set(block, min, list, allowed, disallowed);
} catch { } catch {
Logger.Log(LogType.Warning, "Hit an error on the block " + line); Logger.Log(LogType.Warning, "Hit an error on the block " + line);
continue; continue;
@ -139,19 +172,20 @@ namespace MCGalaxy.Blocks
} }
} }
static void Set(BlockID b, LevelPermission min, static void Set(BlockID b, LevelPermission min, BlockPerms[] list,
List<LevelPermission> allowed, List<LevelPermission> disallowed) { List<LevelPermission> allowed, List<LevelPermission> disallowed) {
BlockPerms perms = List[b]; BlockPerms perms = list[b];
if (perms == null) { if (perms == null) {
perms = new BlockPerms(b, min); perms = new BlockPerms(b, min);
List[b] = perms; list[b] = perms;
} }
perms.Init(min, allowed, disallowed); perms.Init(min, allowed, disallowed);
} }
static void SetDefaultPerms() { 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]; BlockProps props = Block.Props[block];
LevelPermission min; LevelPermission min;
@ -167,8 +201,15 @@ namespace MCGalaxy.Blocks
min = DefaultPerm(block); 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) { static LevelPermission DefaultPerm(BlockID block) {

View File

@ -88,7 +88,7 @@ namespace MCGalaxy.Commands
static void SaveCore() { static void SaveCore() {
using (StreamWriter w = new StreamWriter(Paths.CmdExtraPermsFile)) { using (StreamWriter w = new StreamWriter(Paths.CmdExtraPermsFile)) {
WriteHeader(w, "extra command permissions", "extra permissions in some commands", WriteHeader(w, "extra command permissions", "extra permissions in some commands",
"CommandName:ExtraPermissionNumber", "countdown:1"); "CommandName:ExtraPermissionNumber", "countdown:1", "use");
foreach (CommandExtraPerms perms in list) { foreach (CommandExtraPerms perms in list) {
w.WriteLine(perms.Serialise()); w.WriteLine(perms.Serialise());

View File

@ -77,7 +77,7 @@ namespace MCGalaxy.Commands
static void SaveCore() { static void SaveCore() {
using (StreamWriter w = new StreamWriter(Paths.CmdPermsFile)) { 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) foreach (CommandPerms perms in List)
{ {

View File

@ -99,13 +99,13 @@ namespace MCGalaxy
protected static void WriteHeader(StreamWriter w, string itemName, string itemDesc, 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("#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("# How permissions work:");
w.WriteLine("# - If the player's rank is in Disallowed, they cannot 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 use the {0}", itemName); 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 use the {0}", itemName); w.WriteLine("# - Otherwise if the player's rank is >= Lowest Rank, they can {1} the {0}", itemName, action);
w.WriteLine("#"); w.WriteLine("#");
w.WriteLine("# Layout: {0} : LowestRank : Disallowed : Allowed", headerName); w.WriteLine("# Layout: {0} : LowestRank : Disallowed : Allowed", headerName);
w.WriteLine("# e.g. {0} : 60 : 80,67 : 40,41,55", headerExample); w.WriteLine("# e.g. {0} : 60 : 80,67 : 40,41,55", headerExample);

View File

@ -159,8 +159,12 @@ namespace MCGalaxy.Drawing.Ops
if (old == Block.custom_block) old = (BlockID)(Block.Extended | lvl.FastGetExtTile(b.X, b.Y, b.Z)); if (old == Block.custom_block) old = (BlockID)(Block.Extended | lvl.FastGetExtTile(b.X, b.Y, b.Z));
#endif #endif
// Check to make sure the block is actually different and that can be used // Check to make sure the block is actually different
if (old == b.Block || !p.group.Blocks[old] || !p.group.Blocks[b.Block]) return; if (old == b.Block) return;
// And check that the block can be used
Group grp = p.group;
if (!grp.CanDelete[old] || !grp.CanPlace[b.Block]) return;
// Check if player can affect block at coords in world // Check if player can affect block at coords in world
AccessController denier = lvl.CanAffect(p, b.X, b.Y, b.Z); AccessController denier = lvl.CanAffect(p, b.X, b.Y, b.Z);

View File

@ -220,13 +220,7 @@ namespace MCGalaxy {
blocks[index] = (BlockRaw)block; 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;
}
/// <summary> Returns the AccessController denying the player from changing blocks at the given coordinates. </summary> /// <summary> Returns the AccessController denying the player from changing blocks at the given coordinates. </summary>
/// <remarks> If no AccessController denies the player, returns null. </remarks> /// <remarks> If no AccessController denies the player, returns null. </remarks>
@ -265,7 +259,7 @@ namespace MCGalaxy {
} }
public bool CheckAffect(Player p, ushort x, ushort y, ushort z, BlockID old, BlockID block) { 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); AccessController denier = CanAffect(p, x, y, z);
if (denier == null) return true; if (denier == null) return true;

View File

@ -205,13 +205,14 @@ namespace MCGalaxy
int size = extBlocks ? 5 : 4; int size = extBlocks ? 5 : 4;
byte[] bulk = new byte[count * size]; 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); 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 // NOTE: If you can't delete air, then you're no longer able to place blocks
// (see ClassiCube client #815) // (see ClassiCube client #815)
// TODO: Maybe better solution than this? // 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 // Placing air is the same as deleting existing block at that position in the world
if (block == Block.Air) place &= delete; if (block == Block.Air) place &= delete;

View File

@ -69,7 +69,8 @@ namespace MCGalaxy
internal string filename; internal string filename;
public PlayerList Players; 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() { } public Group() { }
private Group(LevelPermission perm, int drawLimit, int undoMins, string name, string color, int volume, int realms) { 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) { public static Group Find(string name) {
MapName(ref name); MapName(ref name);
foreach (Group grp in GroupList) { foreach (Group grp in GroupList)
{
if (grp.Name.CaselessEq(name)) return grp; if (grp.Name.CaselessEq(name)) return grp;
} }
return null; return null;

View File

@ -132,9 +132,9 @@ namespace MCGalaxy
} }
internal bool CheckManualChange(BlockID old, bool deleteMode) { 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"; string action = deleteMode ? "delete" : "replace";
BlockPerms.Find(old).MessageCannotUse(this, action); BlockPerms.GetDelete(old).MessageCannotUse(this, action);
return false; return false;
} }
return true; return true;

View File

@ -331,7 +331,7 @@ namespace MCGalaxy {
public const string USERNAME_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890._"; 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 #endregion

View File

@ -38,7 +38,10 @@ namespace MCGalaxy
public const string JokerFile = "text/joker.txt"; public const string JokerFile = "text/joker.txt";
public const string EightBallFile = "text/8ball.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 CmdPermsFile = "properties/command.properties";
public const string CmdExtraPermsFile = "properties/ExtraCommandPermissions.properties"; public const string CmdExtraPermsFile = "properties/ExtraCommandPermissions.properties";
public const string EconomyPropsFile = "properties/economy.properties"; public const string EconomyPropsFile = "properties/economy.properties";