diff --git a/Levels/Level.Fields.cs b/Levels/Level.Fields.cs index d7e7b19bd..e7ef6d8d4 100644 --- a/Levels/Level.Fields.cs +++ b/Levels/Level.Fields.cs @@ -141,6 +141,8 @@ namespace MCGalaxy { public bool Buildable = true; [ConfigBool("Deletable", "Permissions", null, true)] public bool Deletable = true; + public LevelAccess VisitAccess, BuildAccess; + [ConfigPerm("PerBuildMax", "Permissions", null, LevelPermission.Nobody, true)] public LevelPermission perbuildmax = LevelPermission.Nobody; [ConfigPerm("PerBuild", "Permissions", null, LevelPermission.Guest, true)] @@ -149,13 +151,16 @@ namespace MCGalaxy { [ConfigPerm("PerVisit", "Permissions", null, LevelPermission.Guest, true)] public LevelPermission permissionvisit = LevelPermission.Guest; [ConfigPerm("PerVisitMax", "Permissions", null, LevelPermission.Nobody, true)] - public LevelPermission pervisitmax = LevelPermission.Nobody; + public LevelPermission pervisitmax = LevelPermission.Nobody; // Other blacklists/whitelists [ConfigStringList("VisitWhitelist", "Permissions", null)] public List VisitWhitelist = new List(); [ConfigStringList("VisitBlacklist", "Permissions", null)] public List VisitBlacklist = new List(); - + [ConfigStringList("BuildWhitelist", "Permissions", null)] + public List BuildWhitelist = new List(); + [ConfigStringList("BuildBlacklist", "Permissions", null)] + public List BuildBlacklist = new List(); // Physics fields and settings public int physics { diff --git a/Levels/Level.cs b/Levels/Level.cs index 6a82c19b4..9cfb69440 100644 --- a/Levels/Level.cs +++ b/Levels/Level.cs @@ -60,6 +60,9 @@ namespace MCGalaxy { if (Height < 16) Height = 16; if (Length < 16) Length = 16; + VisitAccess = new LevelAccess(this, true); + BuildAccess = new LevelAccess(this, false); + #pragma warning disable 0612 width = Width; length = Height; @@ -136,17 +139,11 @@ namespace MCGalaxy { public bool CanJoin(Player p) { if (p == null) return true; - if (Player.BlacklistCheck(p.name, name) || VisitBlacklist.CaselessContains(p.name)) { + if (Player.BlacklistCheck(p.name, name)) { Player.Message(p, "You are blacklisted from going to {0}.", name); return false; } - bool whitelisted = VisitWhitelist.CaselessContains(p.name); - if (!p.ignorePermission && !whitelisted && p.Rank < permissionvisit) { - Player.Message(p, "You are not allowed to go to {0}.", name); return false; - } - if (!p.ignorePermission && !whitelisted && p.Rank > pervisitmax && !p.group.CanExecute("pervisitmax")) { - Player.Message(p, "Your rank must be ranked {1} or lower to go to {0}.", name, pervisitmax); return false; - } + if (!VisitAccess.CheckDetailed(p, p.ignorePermission)) return false; if (File.Exists("text/lockdown/map/" + name)) { Player.Message(p, "The level " + name + " is locked."); return false; } diff --git a/Levels/LevelAccess.cs b/Levels/LevelAccess.cs new file mode 100644 index 000000000..2af60a6d5 --- /dev/null +++ b/Levels/LevelAccess.cs @@ -0,0 +1,93 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using System.Collections.Generic; + +namespace MCGalaxy { + + /// Encapuslates access permissions (visit or build) for a level. + public sealed class LevelAccess { + + /// Whether these access permissions apply to + /// visit (true) or build (false) permission for the level. + public readonly bool IsVisit; + readonly Level lvl; + + public LevelAccess(Level lvl, bool isVisit) { + this.lvl = lvl; + IsVisit = isVisit; + } + + /// Lowest allowed rank. + public LevelPermission Min { + get { return IsVisit ? lvl.permissionvisit : lvl.permissionbuild; } + } + + /// Highest allowed rank. + public LevelPermission Max { + get { return IsVisit ? lvl.pervisitmax : lvl.perbuildmax; } + } + + /// List of always allowed players, overrides rank allowances. + public List Whitelisted { + get { return IsVisit ? lvl.VisitWhitelist : lvl.BuildWhitelist; } + } + + /// List of never allowed players, ignores rank allowances. + public List Blacklisted { + get { return IsVisit ? lvl.VisitBlacklist : lvl.BuildBlacklist; } + } + + /// Returns whether the given player is allowed by these access permissions. + public bool Check(Player p, bool ignoreRankPerm = false) { + if (Blacklisted.CaselessContains(p.name)) return false; + if (Whitelisted.CaselessContains(p.name) || ignoreRankPerm) return true; + + if (p.Rank < Min) return false; + string maxCmd = IsVisit ? "pervisitmax" : "perbuildmax"; + if (p.Rank > Max && !p.group.CanExecute(maxCmd)) return false; + return true; + } + + /// Returns whether the given player is allowed for these access permissions. + /// If the player is not allowed by these access permissions, + /// sends a message to the player describing why they are not. + public bool CheckDetailed(Player p, bool ignoreRankPerm = false) { + string name = lvl.name; + string action = IsVisit ? "going to" : "building in"; + if (Blacklisted.CaselessContains(p.name)) { + Player.Message(p, "You are blacklisted from {1} {0}.", name, action); return false; + } + if (Whitelisted.CaselessContains(p.name) || ignoreRankPerm) return true; + + action = IsVisit? "go to" : "build in"; + if (p.Rank < Min) { + Group grp = Group.findPerm(Min); + string grpName = grp == null ? "&f" + Min : grp.ColoredName; + Player.Message(p, "Only {2}%S+ may {1} {0}.", name, action, grpName); return false; + } + + string maxCmd = IsVisit ? "pervisitmax" : "perbuildmax"; + if (p.Rank > Max && !p.group.CanExecute(maxCmd)) { + Group grp = Group.findPerm(Max); + string grpName = grp == null ? "&f" + Max : grp.ColoredName; + Player.Message(p, "Only {2} and below may {1} in {0}.", name, action, grpName) return false; + } + } + } +} diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index 2ee79ff9f..2802ed379 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -497,6 +497,7 @@ +