Add PlayerPermission hook, replace p.Group.HasPermission by p.HasPermission everywhere possible.

This commit is contained in:
Enerdy 2016-01-11 14:33:44 +00:00
parent 21f16e5908
commit aa419283a9
13 changed files with 467 additions and 232 deletions

View file

@ -175,7 +175,7 @@ namespace TShockAPI
return true; return true;
foreach (var Permission in Permissions) foreach (var Permission in Permissions)
{ {
if (ply.Group.HasPermission(Permission)) if (ply.HasPermission(Permission))
return true; return true;
} }
return false; return false;
@ -795,7 +795,7 @@ namespace TShockAPI
if (Main.ServerSideCharacter) if (Main.ServerSideCharacter)
{ {
if (group.HasPermission(Permissions.bypassssc)) if (args.Player.HasPermission(Permissions.bypassssc))
{ {
args.Player.IgnoreActionsForClearingTrashCan = false; args.Player.IgnoreActionsForClearingTrashCan = false;
} }
@ -803,10 +803,10 @@ namespace TShockAPI
} }
args.Player.LoginFailsBySsi = false; args.Player.LoginFailsBySsi = false;
if (group.HasPermission(Permissions.ignorestackhackdetection)) if (args.Player.HasPermission(Permissions.ignorestackhackdetection))
args.Player.IgnoreActionsForCheating = "none"; args.Player.IgnoreActionsForCheating = "none";
if (group.HasPermission(Permissions.usebanneditem)) if (args.Player.HasPermission(Permissions.usebanneditem))
args.Player.IgnoreActionsForDisabledArmor = "none"; args.Player.IgnoreActionsForDisabledArmor = "none";
args.Player.Group = group; args.Player.Group = group;
@ -1381,7 +1381,7 @@ namespace TShockAPI
TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name)); TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name));
else else
{ {
if (args.Player.RealPlayer && players[0].Group.HasPermission(Permissions.immunetoban)) if (args.Player.RealPlayer && players[0].HasPermission(Permissions.immunetoban))
{ {
args.Player.SendErrorMessage("You can't ban {0}!", players[0].Name); args.Player.SendErrorMessage("You can't ban {0}!", players[0].Name);
return; return;
@ -2237,7 +2237,7 @@ namespace TShockAPI
{ {
if (args.Parameters.Count != 1 && args.Parameters.Count != 2) if (args.Parameters.Count != 1 && args.Parameters.Count != 2)
{ {
if (args.Player.Group.HasPermission(Permissions.tpothers)) if (args.Player.HasPermission(Permissions.tpothers))
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tp <player> [player 2]", Specifier); args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tp <player> [player 2]", Specifier);
else else
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tp <player>", Specifier); args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tp <player>", Specifier);
@ -2254,7 +2254,7 @@ namespace TShockAPI
else else
{ {
var target = players[0]; var target = players[0];
if (!target.TPAllow && !args.Player.Group.HasPermission(Permissions.tpoverride)) if (!target.TPAllow && !args.Player.HasPermission(Permissions.tpoverride))
{ {
args.Player.SendErrorMessage("{0} has disabled players from teleporting.", target.Name); args.Player.SendErrorMessage("{0} has disabled players from teleporting.", target.Name);
return; return;
@ -2262,14 +2262,14 @@ namespace TShockAPI
if (args.Player.Teleport(target.TPlayer.position.X, target.TPlayer.position.Y)) if (args.Player.Teleport(target.TPlayer.position.X, target.TPlayer.position.Y))
{ {
args.Player.SendSuccessMessage("Teleported to {0}.", target.Name); args.Player.SendSuccessMessage("Teleported to {0}.", target.Name);
if (!args.Player.Group.HasPermission(Permissions.tpsilent)) if (!args.Player.HasPermission(Permissions.tpsilent))
target.SendInfoMessage("{0} teleported to you.", args.Player.Name); target.SendInfoMessage("{0} teleported to you.", args.Player.Name);
} }
} }
} }
else else
{ {
if (!args.Player.Group.HasPermission(Permissions.tpothers)) if (!args.Player.HasPermission(Permissions.tpothers))
{ {
args.Player.SendErrorMessage("You do not have access to this command."); args.Player.SendErrorMessage("You do not have access to this command.");
return; return;
@ -2286,7 +2286,7 @@ namespace TShockAPI
{ {
if (args.Parameters[0] == "*") if (args.Parameters[0] == "*")
{ {
if (!args.Player.Group.HasPermission(Permissions.tpallothers)) if (!args.Player.HasPermission(Permissions.tpallothers))
{ {
args.Player.SendErrorMessage("You do not have access to this command."); args.Player.SendErrorMessage("You do not have access to this command.");
return; return;
@ -2295,22 +2295,22 @@ namespace TShockAPI
var target = players2[0]; var target = players2[0];
foreach (var source in TShock.Players.Where(p => p != null && p != args.Player)) foreach (var source in TShock.Players.Where(p => p != null && p != args.Player))
{ {
if (!target.TPAllow && !args.Player.Group.HasPermission(Permissions.tpoverride)) if (!target.TPAllow && !args.Player.HasPermission(Permissions.tpoverride))
continue; continue;
if (source.Teleport(target.TPlayer.position.X, target.TPlayer.position.Y)) if (source.Teleport(target.TPlayer.position.X, target.TPlayer.position.Y))
{ {
if (args.Player != source) if (args.Player != source)
{ {
if (args.Player.Group.HasPermission(Permissions.tpsilent)) if (args.Player.HasPermission(Permissions.tpsilent))
source.SendSuccessMessage("You were teleported to {0}.", target.Name); source.SendSuccessMessage("You were teleported to {0}.", target.Name);
else else
source.SendSuccessMessage("{0} teleported you to {1}.", args.Player.Name, target.Name); source.SendSuccessMessage("{0} teleported you to {1}.", args.Player.Name, target.Name);
} }
if (args.Player != target) if (args.Player != target)
{ {
if (args.Player.Group.HasPermission(Permissions.tpsilent)) if (args.Player.HasPermission(Permissions.tpsilent))
target.SendInfoMessage("{0} was teleported to you.", source.Name); target.SendInfoMessage("{0} was teleported to you.", source.Name);
if (!args.Player.Group.HasPermission(Permissions.tpsilent)) if (!args.Player.HasPermission(Permissions.tpsilent))
target.SendInfoMessage("{0} teleported {1} to you.", args.Player.Name, source.Name); target.SendInfoMessage("{0} teleported {1} to you.", args.Player.Name, source.Name);
} }
} }
@ -2325,13 +2325,13 @@ namespace TShockAPI
else else
{ {
var source = players1[0]; var source = players1[0];
if (!source.TPAllow && !args.Player.Group.HasPermission(Permissions.tpoverride)) if (!source.TPAllow && !args.Player.HasPermission(Permissions.tpoverride))
{ {
args.Player.SendErrorMessage("{0} has disabled players from teleporting.", source.Name); args.Player.SendErrorMessage("{0} has disabled players from teleporting.", source.Name);
return; return;
} }
var target = players2[0]; var target = players2[0];
if (!target.TPAllow && !args.Player.Group.HasPermission(Permissions.tpoverride)) if (!target.TPAllow && !args.Player.HasPermission(Permissions.tpoverride))
{ {
args.Player.SendErrorMessage("{0} has disabled players from teleporting.", target.Name); args.Player.SendErrorMessage("{0} has disabled players from teleporting.", target.Name);
return; return;
@ -2341,16 +2341,16 @@ namespace TShockAPI
{ {
if (args.Player != source) if (args.Player != source)
{ {
if (args.Player.Group.HasPermission(Permissions.tpsilent)) if (args.Player.HasPermission(Permissions.tpsilent))
source.SendSuccessMessage("You were teleported to {0}.", target.Name); source.SendSuccessMessage("You were teleported to {0}.", target.Name);
else else
source.SendSuccessMessage("{0} teleported you to {1}.", args.Player.Name, target.Name); source.SendSuccessMessage("{0} teleported you to {1}.", args.Player.Name, target.Name);
} }
if (args.Player != target) if (args.Player != target)
{ {
if (args.Player.Group.HasPermission(Permissions.tpsilent)) if (args.Player.HasPermission(Permissions.tpsilent))
target.SendInfoMessage("{0} was teleported to you.", source.Name); target.SendInfoMessage("{0} was teleported to you.", source.Name);
if (!args.Player.Group.HasPermission(Permissions.tpsilent)) if (!args.Player.HasPermission(Permissions.tpsilent))
target.SendInfoMessage("{0} teleported {1} to you.", args.Player.Name, source.Name); target.SendInfoMessage("{0} teleported {1} to you.", args.Player.Name, source.Name);
} }
} }
@ -2362,7 +2362,7 @@ namespace TShockAPI
{ {
if (args.Parameters.Count < 1) if (args.Parameters.Count < 1)
{ {
if (args.Player.Group.HasPermission(Permissions.tpallothers)) if (args.Player.HasPermission(Permissions.tpallothers))
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tphere <player|*>", Specifier); args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tphere <player|*>", Specifier);
else else
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tphere <player>", Specifier); args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tphere <player>", Specifier);
@ -2375,7 +2375,7 @@ namespace TShockAPI
{ {
if (playerName == "*") if (playerName == "*")
{ {
if (!args.Player.Group.HasPermission(Permissions.tpallothers)) if (!args.Player.HasPermission(Permissions.tpallothers))
{ {
args.Player.SendErrorMessage("You do not have permission to use this command."); args.Player.SendErrorMessage("You do not have permission to use this command.");
return; return;
@ -2500,7 +2500,7 @@ namespace TShockAPI
private static void Warp(CommandArgs args) private static void Warp(CommandArgs args)
{ {
bool hasManageWarpPermission = args.Player.Group.HasPermission(Permissions.managewarp); bool hasManageWarpPermission = args.Player.HasPermission(Permissions.managewarp);
if (args.Parameters.Count < 1) if (args.Parameters.Count < 1)
{ {
if (hasManageWarpPermission) if (hasManageWarpPermission)
@ -2603,7 +2603,7 @@ namespace TShockAPI
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}warp hide [name] <true/false>", Specifier); args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}warp hide [name] <true/false>", Specifier);
#endregion #endregion
} }
else if (args.Parameters[0].ToLower() == "send" && args.Player.Group.HasPermission(Permissions.tpothers)) else if (args.Parameters[0].ToLower() == "send" && args.Player.HasPermission(Permissions.tpothers))
{ {
#region Warp send #region Warp send
if (args.Parameters.Count < 3) if (args.Parameters.Count < 3)
@ -3852,7 +3852,7 @@ namespace TShockAPI
{ {
int.TryParse(args.Parameters[1], out damage); int.TryParse(args.Parameters[1], out damage);
} }
if (!args.Player.Group.HasPermission(Permissions.kill)) if (!args.Player.HasPermission(Permissions.kill))
{ {
damage = TShock.Utils.Clamp(damage, 15, 0); damage = TShock.Utils.Clamp(damage, 15, 0);
} }
@ -4349,7 +4349,7 @@ namespace TShockAPI
} }
case "tp": case "tp":
{ {
if (!args.Player.Group.HasPermission(Permissions.tp)) if (!args.Player.HasPermission(Permissions.tp))
{ {
args.Player.SendErrorMessage("You don't have the necessary permission to do that."); args.Player.SendErrorMessage("You don't have the necessary permission to do that.");
break; break;
@ -4397,7 +4397,7 @@ namespace TShockAPI
"protect <name> <true/false> - Sets whether the tiles inside the region are protected or not.", "protect <name> <true/false> - Sets whether the tiles inside the region are protected or not.",
"z <name> <#> - Sets the z-order of the region.", "z <name> <#> - Sets the z-order of the region.",
}; };
if (args.Player.Group.HasPermission(Permissions.tp)) if (args.Player.HasPermission(Permissions.tp))
lines.Add("tp <region> - Teleports you to the given region's center."); lines.Add("tp <region> - Teleports you to the given region's center.");
PaginationTools.SendPage( PaginationTools.SendPage(
@ -4526,7 +4526,7 @@ namespace TShockAPI
args.Player.SendErrorMessage("Invalid usage, proper usage: {0}who [-i] [pagenumber]", Specifier); args.Player.SendErrorMessage("Invalid usage, proper usage: {0}who [-i] [pagenumber]", Specifier);
return; return;
} }
if (displayIdsRequested && !args.Player.Group.HasPermission(Permissions.seeids)) if (displayIdsRequested && !args.Player.HasPermission(Permissions.seeids))
{ {
args.Player.SendErrorMessage("You don't have the required permission to list player ids."); args.Player.SendErrorMessage("You don't have the required permission to list player ids.");
return; return;
@ -4658,7 +4658,7 @@ namespace TShockAPI
{ {
TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name)); TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name));
} }
else if (players[0].Group.HasPermission(Permissions.mute)) else if (players[0].HasPermission(Permissions.mute))
{ {
args.Player.SendErrorMessage("You cannot mute this player."); args.Player.SendErrorMessage("You cannot mute this player.");
} }
@ -5497,7 +5497,7 @@ namespace TShockAPI
TSPlayer playerToGod; TSPlayer playerToGod;
if (args.Parameters.Count > 0) if (args.Parameters.Count > 0)
{ {
if (!args.Player.Group.HasPermission(Permissions.godmodeother)) if (!args.Player.HasPermission(Permissions.godmodeother))
{ {
args.Player.SendErrorMessage("You do not have permission to god mode another player!"); args.Player.SendErrorMessage("You do not have permission to god mode another player!");
return; return;

View file

@ -162,13 +162,13 @@ namespace TShockAPI.DB
if (!player.IsLoggedIn) if (!player.IsLoggedIn)
return false; return false;
if ((player.tempGroup != null && player.tempGroup.HasPermission(Permissions.bypassssc)) || player.Group.HasPermission(Permissions.bypassssc)) if (player.HasPermission(Permissions.bypassssc))
{ {
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + player.User.Name); // Debug code TShock.Log.ConsoleInfo("Skipping SSC Backup for " + player.User.Name); // Debug code
return true; return true;
} }
if (!GetPlayerData(player, player.User.ID).exists) if (!GetPlayerData(player, player.User.ID).exists)
{ {
try try

View file

@ -192,32 +192,32 @@ namespace TShockAPI.DB
return Name == other.Name; return Name == other.Name;
} }
public bool HasPermissionToUseItem(TSPlayer ply) public bool HasPermissionToUseItem(TSPlayer ply)
{ {
if (ply == null) if (ply == null)
return false; return false;
if (ply.Group.HasPermission(Permissions.usebanneditem)) if (ply.HasPermission(Permissions.usebanneditem))
return true; return true;
var cur = ply.Group; var cur = ply.Group;
var traversed = new List<Group>(); var traversed = new List<Group>();
while (cur != null) while (cur != null)
{ {
if (AllowedGroups.Contains(cur.Name)) if (AllowedGroups.Contains(cur.Name))
{ {
return true; return true;
} }
if (traversed.Contains(cur)) if (traversed.Contains(cur))
{ {
throw new InvalidOperationException("Infinite group parenting ({0})".SFormat(cur.Name)); throw new InvalidOperationException("Infinite group parenting ({0})".SFormat(cur.Name));
} }
traversed.Add(cur); traversed.Add(cur);
cur = cur.Parent; cur = cur.Parent;
} }
return false; return false;
// could add in the other permissions in this class instead of a giant if switch. // could add in the other permissions in this class instead of a giant if switch.
} }
public void SetAllowedGroups(String groups) public void SetAllowedGroups(String groups)
{ {

View file

@ -202,7 +202,7 @@ namespace TShockAPI.DB
if (ply == null) if (ply == null)
return false; return false;
if (ply.Group.HasPermission(Permissions.canusebannedprojectiles)) if (ply.HasPermission(Permissions.canusebannedprojectiles))
return true; return true;
var cur = ply.Group; var cur = ply.Group;

View file

@ -210,7 +210,7 @@ namespace TShockAPI.DB
public bool CanBuild(int x, int y, TSPlayer ply) public bool CanBuild(int x, int y, TSPlayer ply)
{ {
if (!ply.Group.HasPermission(Permissions.canbuild)) if (!ply.HasPermission(Permissions.canbuild))
{ {
return false; return false;
} }

View file

@ -202,7 +202,7 @@ namespace TShockAPI.DB
if (ply == null) if (ply == null)
return false; return false;
if (ply.Group.HasPermission(Permissions.canusebannedtiles)) if (ply.HasPermission(Permissions.canusebannedtiles))
return true; return true;
var cur = ply.Group; var cur = ply.Group;

View file

@ -1305,7 +1305,7 @@ namespace TShockAPI
args.Player.PlayerData.StoreSlot(slot, type, prefix, stack); args.Player.PlayerData.StoreSlot(slot, type, prefix, stack);
} }
else if (Main.ServerSideCharacter && TShock.Config.DisableLoginBeforeJoin && !bypassTrashCanCheck && else if (Main.ServerSideCharacter && TShock.Config.DisableLoginBeforeJoin && !bypassTrashCanCheck &&
args.Player.HasSentInventory && !args.Player.Group.HasPermission(Permissions.bypassssc)) args.Player.HasSentInventory && !args.Player.HasPermission(Permissions.bypassssc))
{ {
// The player might have moved an item to their trash can before they performed a single login attempt yet. // The player might have moved an item to their trash can before they performed a single login attempt yet.
args.Player.IgnoreActionsForClearingTrashCan = true; args.Player.IgnoreActionsForClearingTrashCan = true;
@ -1329,7 +1329,7 @@ namespace TShockAPI
if (OnPlayerHP(plr, cur, max) || cur <= 0 || max <= 0 || args.Player.IgnoreSSCPackets) if (OnPlayerHP(plr, cur, max) || cur <= 0 || max <= 0 || args.Player.IgnoreSSCPackets)
return true; return true;
if (max > TShock.Config.MaxHP && !args.Player.Group.HasPermission(Permissions.ignorehp)) if (max > TShock.Config.MaxHP && !args.Player.HasPermission(Permissions.ignorehp))
{ {
args.Player.Disable("Maximum HP beyond limit", DisableFlags.WriteToLogAndConsole); args.Player.Disable("Maximum HP beyond limit", DisableFlags.WriteToLogAndConsole);
return true; return true;
@ -1358,7 +1358,7 @@ namespace TShockAPI
if (OnPlayerMana(plr, cur, max) || cur < 0 || max < 0 || args.Player.IgnoreSSCPackets) if (OnPlayerMana(plr, cur, max) || cur < 0 || max < 0 || args.Player.IgnoreSSCPackets)
return true; return true;
if (max > TShock.Config.MaxMP && !args.Player.Group.HasPermission(Permissions.ignoremp)) if (max > TShock.Config.MaxMP && !args.Player.HasPermission(Permissions.ignoremp))
{ {
args.Player.Disable("Maximum MP beyond limit", DisableFlags.WriteToLogAndConsole); args.Player.Disable("Maximum MP beyond limit", DisableFlags.WriteToLogAndConsole);
return true; return true;
@ -1476,17 +1476,17 @@ namespace TShockAPI
if (Main.ServerSideCharacter) if (Main.ServerSideCharacter)
{ {
if (!group.HasPermission(Permissions.bypassssc)) if (!args.Player.HasPermission(Permissions.bypassssc))
{ {
args.Player.PlayerData.RestoreCharacter(args.Player); args.Player.PlayerData.RestoreCharacter(args.Player);
} }
} }
args.Player.LoginFailsBySsi = false; args.Player.LoginFailsBySsi = false;
if (group.HasPermission(Permissions.ignorestackhackdetection)) if (args.Player.HasPermission(Permissions.ignorestackhackdetection))
args.Player.IgnoreActionsForCheating = "none"; args.Player.IgnoreActionsForCheating = "none";
if (group.HasPermission(Permissions.usebanneditem)) if (args.Player.HasPermission(Permissions.usebanneditem))
args.Player.IgnoreActionsForDisabledArmor = "none"; args.Player.IgnoreActionsForDisabledArmor = "none";
args.Player.Group = group; args.Player.Group = group;
@ -1551,7 +1551,7 @@ namespace TShockAPI
if (Main.ServerSideCharacter) if (Main.ServerSideCharacter)
{ {
if (group.HasPermission(Permissions.bypassssc)) if (args.Player.HasPermission(Permissions.bypassssc))
{ {
args.Player.IgnoreActionsForClearingTrashCan = false; args.Player.IgnoreActionsForClearingTrashCan = false;
} }
@ -1559,10 +1559,10 @@ namespace TShockAPI
} }
args.Player.LoginFailsBySsi = false; args.Player.LoginFailsBySsi = false;
if (group.HasPermission(Permissions.ignorestackhackdetection)) if (args.Player.HasPermission(Permissions.ignorestackhackdetection))
args.Player.IgnoreActionsForCheating = "none"; args.Player.IgnoreActionsForCheating = "none";
if (group.HasPermission(Permissions.usebanneditem)) if (args.Player.HasPermission(Permissions.usebanneditem))
args.Player.IgnoreActionsForDisabledArmor = "none"; args.Player.IgnoreActionsForDisabledArmor = "none";
args.Player.Group = group; args.Player.Group = group;
@ -1614,13 +1614,13 @@ namespace TShockAPI
return true; return true;
} }
if (!args.Player.Group.HasPermission(Permissions.ignorestackhackdetection)) if (!args.Player.HasPermission(Permissions.ignorestackhackdetection))
{ {
TShock.HackedInventory(args.Player); TShock.HackedInventory(args.Player);
} }
if (TShock.Utils.ActivePlayers() + 1 > TShock.Config.MaxSlots && if (TShock.Utils.ActivePlayers() + 1 > TShock.Config.MaxSlots &&
!args.Player.Group.HasPermission(Permissions.reservedslot)) !args.Player.HasPermission(Permissions.reservedslot))
{ {
TShock.Utils.ForceKick(args.Player, TShock.Config.ServerFullReason, true); TShock.Utils.ForceKick(args.Player, TShock.Config.ServerFullReason, true);
return true; return true;
@ -1681,7 +1681,7 @@ namespace TShockAPI
isTrapdoor = true; isTrapdoor = true;
} }
if (args.Player.Group.HasPermission(Permissions.allowclientsideworldedit) && !isTrapdoor) if (args.Player.HasPermission(Permissions.allowclientsideworldedit) && !isTrapdoor)
return false; return false;
if (OnSendTileSquare(size, tileX, tileY)) if (OnSendTileSquare(size, tileX, tileY))
@ -2133,7 +2133,7 @@ namespace TShockAPI
return true; return true;
} }
if ((action == EditAction.PlaceTile || action == EditAction.PlaceWall) && !args.Player.Group.HasPermission(Permissions.ignoreplacetiledetection)) if ((action == EditAction.PlaceTile || action == EditAction.PlaceWall) && !args.Player.HasPermission(Permissions.ignoreplacetiledetection))
{ {
args.Player.TilePlaceThreshold++; args.Player.TilePlaceThreshold++;
var coords = new Vector2(tileX, tileY); var coords = new Vector2(tileX, tileY);
@ -2142,7 +2142,7 @@ namespace TShockAPI
} }
if ((action == EditAction.KillTile || action == EditAction.KillTileNoItem || action == EditAction.KillWall) && Main.tileSolid[Main.tile[tileX, tileY].type] && if ((action == EditAction.KillTile || action == EditAction.KillTileNoItem || action == EditAction.KillWall) && Main.tileSolid[Main.tile[tileX, tileY].type] &&
!args.Player.Group.HasPermission(Permissions.ignorekilltiledetection)) !args.Player.HasPermission(Permissions.ignorekilltiledetection))
{ {
args.Player.TileKillThreshold++; args.Player.TileKillThreshold++;
var coords = new Vector2(tileX, tileY); var coords = new Vector2(tileX, tileY);
@ -2235,7 +2235,7 @@ namespace TShockAPI
return true; return true;
} }
if (!args.Player.Group.HasPermission(Permissions.ignoreplacetiledetection)) if (!args.Player.HasPermission(Permissions.ignoreplacetiledetection))
{ {
args.Player.TilePlaceThreshold++; args.Player.TilePlaceThreshold++;
var coords = new Vector2(x, y); var coords = new Vector2(x, y);
@ -2437,7 +2437,7 @@ namespace TShockAPI
return true; return true;
} }
if (!args.Player.Group.HasPermission(Permissions.ignorenoclipdetection) && if (!args.Player.HasPermission(Permissions.ignorenoclipdetection) &&
TSCheckNoclip(pos, args.TPlayer.width, args.TPlayer.height) && !TShock.Config.IgnoreNoClip TSCheckNoclip(pos, args.TPlayer.width, args.TPlayer.height) && !TShock.Config.IgnoreNoClip
&& !args.TPlayer.tongued) && !args.TPlayer.tongued)
{ {
@ -2617,7 +2617,7 @@ namespace TShockAPI
return true; return true;
} }
if (dmg > TShock.Config.MaxProjDamage && !args.Player.Group.HasPermission(Permissions.ignoredamagecap)) if (dmg > TShock.Config.MaxProjDamage && !args.Player.HasPermission(Permissions.ignoredamagecap))
{ {
args.Player.Disable(String.Format("Projectile damage is higher than {0}.", TShock.Config.MaxProjDamage), DisableFlags.WriteToLogAndConsole); args.Player.Disable(String.Format("Projectile damage is higher than {0}.", TShock.Config.MaxProjDamage), DisableFlags.WriteToLogAndConsole);
args.Player.RemoveProjectile(ident, owner); args.Player.RemoveProjectile(ident, owner);
@ -2631,7 +2631,7 @@ namespace TShockAPI
} }
bool hasPermission = !TShock.CheckProjectilePermission(args.Player, index, type); bool hasPermission = !TShock.CheckProjectilePermission(args.Player, index, type);
if (!TShock.Config.IgnoreProjUpdate && !hasPermission && !args.Player.Group.HasPermission(Permissions.ignoreprojectiledetection)) if (!TShock.Config.IgnoreProjUpdate && !hasPermission && !args.Player.HasPermission(Permissions.ignoreprojectiledetection))
{ {
if (type == ProjectileID.BlowupSmokeMoonlord if (type == ProjectileID.BlowupSmokeMoonlord
|| type == ProjectileID.PhantasmalEye || type == ProjectileID.PhantasmalEye
@ -2668,7 +2668,7 @@ namespace TShockAPI
return true; return true;
} }
if (!args.Player.Group.HasPermission(Permissions.ignoreprojectiledetection)) if (!args.Player.HasPermission(Permissions.ignoreprojectiledetection))
{ {
if (type == ProjectileID.CrystalShard && TShock.Config.ProjIgnoreShrapnel) // Ignore crystal shards if (type == ProjectileID.CrystalShard && TShock.Config.ProjIgnoreShrapnel) // Ignore crystal shards
{ {
@ -2831,7 +2831,7 @@ namespace TShockAPI
return true; return true;
} }
if (!args.Player.Group.HasPermission(Permissions.ignoreliquidsetdetection)) if (!args.Player.HasPermission(Permissions.ignoreliquidsetdetection))
{ {
args.Player.TileLiquidThreshold++; args.Player.TileLiquidThreshold++;
} }
@ -3149,7 +3149,7 @@ namespace TShockAPI
if (OnUpdateNPCHome(id, x, y, homeless)) if (OnUpdateNPCHome(id, x, y, homeless))
return true; return true;
if (!args.Player.Group.HasPermission(Permissions.movenpc)) if (!args.Player.HasPermission(Permissions.movenpc))
{ {
args.Player.SendErrorMessage("You do not have permission to relocate NPCs."); args.Player.SendErrorMessage("You do not have permission to relocate NPCs.");
args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY,
@ -3281,7 +3281,7 @@ namespace TShockAPI
Item item = new Item(); Item item = new Item();
item.netDefaults(type); item.netDefaults(type);
if ((stacks > item.maxStack || stacks <= 0) || (TShock.Itembans.ItemIsBanned(item.name, args.Player) && !args.Player.Group.HasPermission(Permissions.allowdroppingbanneditems))) if ((stacks > item.maxStack || stacks <= 0) || (TShock.Itembans.ItemIsBanned(item.name, args.Player) && !args.Player.HasPermission(Permissions.allowdroppingbanneditems)))
{ {
args.Player.SendData(PacketTypes.ItemDrop, "", id); args.Player.SendData(PacketTypes.ItemDrop, "", id);
return true; return true;
@ -3338,7 +3338,7 @@ namespace TShockAPI
return true; return true;
} }
if (dmg > TShock.Config.MaxDamage && !args.Player.Group.HasPermission(Permissions.ignoredamagecap) && id != args.Player.Index) if (dmg > TShock.Config.MaxDamage && !args.Player.HasPermission(Permissions.ignoredamagecap) && id != args.Player.Index)
{ {
if (TShock.Config.KickOnDamageThresholdBroken) if (TShock.Config.KickOnDamageThresholdBroken)
{ {
@ -3404,7 +3404,7 @@ namespace TShockAPI
if (Main.npc[id] == null) if (Main.npc[id] == null)
return true; return true;
if (dmg > TShock.Config.MaxDamage && !args.Player.Group.HasPermission(Permissions.ignoredamagecap)) if (dmg > TShock.Config.MaxDamage && !args.Player.HasPermission(Permissions.ignoredamagecap))
{ {
if (TShock.Config.KickOnDamageThresholdBroken) if (TShock.Config.KickOnDamageThresholdBroken)
{ {
@ -3425,7 +3425,7 @@ namespace TShockAPI
return true; return true;
} }
if (Main.npc[id].townNPC && !args.Player.Group.HasPermission(Permissions.hurttownnpc)) if (Main.npc[id].townNPC && !args.Player.HasPermission(Permissions.hurttownnpc))
{ {
args.Player.SendErrorMessage("You do not have permission to hurt this NPC."); args.Player.SendErrorMessage("You do not have permission to hurt this NPC.");
args.Player.SendData(PacketTypes.NpcUpdate, "", id); args.Player.SendData(PacketTypes.NpcUpdate, "", id);
@ -3588,12 +3588,12 @@ namespace TShockAPI
break; break;
} }
} }
if (spawnboss && !args.Player.Group.HasPermission(Permissions.summonboss)) if (spawnboss && !args.Player.HasPermission(Permissions.summonboss))
{ {
args.Player.SendErrorMessage("You don't have permission to summon a boss."); args.Player.SendErrorMessage("You don't have permission to summon a boss.");
return true; return true;
} }
if (invasion && !args.Player.Group.HasPermission(Permissions.startinvasion)) if (invasion && !args.Player.HasPermission(Permissions.startinvasion))
{ {
args.Player.SendErrorMessage("You don't have permission to start an invasion."); args.Player.SendErrorMessage("You don't have permission to start an invasion.");
return true; return true;
@ -3670,7 +3670,7 @@ namespace TShockAPI
return true; return true;
} }
if (!args.Player.Group.HasPermission(Permissions.ignorepaintdetection)) if (!args.Player.HasPermission(Permissions.ignorepaintdetection))
{ {
args.Player.PaintThreshold++; args.Player.PaintThreshold++;
} }
@ -3714,7 +3714,7 @@ namespace TShockAPI
return true; return true;
} }
if (!args.Player.Group.HasPermission(Permissions.ignorepaintdetection)) if (!args.Player.HasPermission(Permissions.ignorepaintdetection))
{ {
args.Player.PaintThreshold++; args.Player.PaintThreshold++;
} }
@ -3753,7 +3753,7 @@ namespace TShockAPI
} }
//Rod of Discord teleport (usually (may be used by modded clients to teleport)) //Rod of Discord teleport (usually (may be used by modded clients to teleport))
if (type == 0 && !args.Player.Group.HasPermission(Permissions.rod)) if (type == 0 && !args.Player.HasPermission(Permissions.rod))
{ {
args.Player.SendErrorMessage("You do not have permission to teleport."); args.Player.SendErrorMessage("You do not have permission to teleport.");
args.Player.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y); args.Player.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y);
@ -3774,7 +3774,7 @@ namespace TShockAPI
return true; return true;
} }
if (!args.Player.Group.HasPermission(Permissions.wormhole)) if (!args.Player.HasPermission(Permissions.wormhole))
{ {
args.Player.SendErrorMessage("You do not have permission to teleport."); args.Player.SendErrorMessage("You do not have permission to teleport.");
args.Player.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y); args.Player.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y);

View file

@ -22,56 +22,59 @@ using System.Collections.Generic;
namespace TShockAPI namespace TShockAPI
{ {
/// <summary>
/// A class used to group multiple users' permissions and settings.
/// </summary>
public class Group public class Group
{ {
// NOTE: Using a const still suffers from needing to recompile to change the default // NOTE: Using a const still suffers from needing to recompile to change the default
// ideally we would use a static but this means it can't be used for the default parameter :( // ideally we would use a static but this means it can't be used for the default parameter :(
/// <summary> /// <summary>
/// Default chat color. /// Default chat color.
/// </summary> /// </summary>
public const string defaultChatColor = "255,255,255"; public const string defaultChatColor = "255,255,255";
/// <summary> /// <summary>
/// List of permissions available to the group. /// List of permissions available to the group.
/// </summary> /// </summary>
public readonly List<string> permissions = new List<string>(); public readonly List<string> permissions = new List<string>();
/// <summary> /// <summary>
/// List of permissions that the group is explicitly barred from. /// List of permissions that the group is explicitly barred from.
/// </summary> /// </summary>
public readonly List<string> negatedpermissions = new List<string>(); public readonly List<string> negatedpermissions = new List<string>();
/// <summary> /// <summary>
/// The group's name. /// The group's name.
/// </summary> /// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// The group that this group inherits permissions from. /// The group that this group inherits permissions from.
/// </summary> /// </summary>
public Group Parent { get; set; } public Group Parent { get; set; }
/// <summary> /// <summary>
/// The chat prefix for this group. /// The chat prefix for this group.
/// </summary> /// </summary>
public string Prefix { get; set; } public string Prefix { get; set; }
/// <summary> /// <summary>
/// The chat suffix for this group. /// The chat suffix for this group.
/// </summary> /// </summary>
public string Suffix { get; set; } public string Suffix { get; set; }
/// <summary> /// <summary>
/// The name of the parent, not particularly sure why this is here. /// The name of the parent, not particularly sure why this is here.
/// We can use group.Parent.Name and not have this second reference. /// We can use group.Parent.Name and not have this second reference.
/// This was added for rest, so a discussion with Shank is necessary. /// This was added for rest, so a discussion with Shank is necessary.
/// </summary> /// </summary>
public string ParentName { get { return (null == Parent) ? "" : Parent.Name; } } public string ParentName { get { return (null == Parent) ? "" : Parent.Name; } }
/// <summary> /// <summary>
/// The chat color of the group. /// The chat color of the group.
/// Returns "255,255,255", sets "255,255,255" /// Returns "255,255,255", sets "255,255,255"
/// </summary> /// </summary>
public string ChatColor public string ChatColor
{ {
get { return string.Format("{0},{1},{2}", R.ToString("D3"), G.ToString("D3"), B.ToString("D3")); } get { return string.Format("{0},{1},{2}", R.ToString("D3"), G.ToString("D3"), B.ToString("D3")); }
@ -95,9 +98,9 @@ namespace TShockAPI
} }
} }
/// <summary> /// <summary>
/// The permissions of the user in string form. /// The permissions of the user in string form.
/// </summary> /// </summary>
public string Permissions public string Permissions
{ {
get get
@ -115,9 +118,9 @@ namespace TShockAPI
} }
} }
/// <summary> /// <summary>
/// The permissions of this group and all that it inherits from. /// The permissions of this group and all that it inherits from.
/// </summary> /// </summary>
public virtual List<string> TotalPermissions public virtual List<string> TotalPermissions
{ {
get get
@ -148,12 +151,31 @@ namespace TShockAPI
} }
} }
/// <summary>
/// The group's chat color red byte.
/// </summary>
public byte R = 255; public byte R = 255;
/// <summary>
/// The group's chat color green byte.
/// </summary>
public byte G = 255; public byte G = 255;
/// <summary>
/// The group's chat color blue byte.
/// </summary>
public byte B = 255; public byte B = 255;
public static Group DefaultGroup = null; /// <summary>
/// The default group attributed to unregistered users.
/// </summary>
public static Group DefaultGroup = null;
/// <summary>
/// Initializes a new instance of the group class.
/// </summary>
/// <param name="groupname">The name of the group.</param>
/// <param name="parentgroup">The parent group, if any.</param>
/// <param name="chatcolor">The chat color, in "RRR,GGG,BBB" format.</param>
/// <param name="permissions">The list of permissions associated with this group, separated by commas.</param>
public Group(string groupname, Group parentgroup = null, string chatcolor = "255,255,255", string permissions = null) public Group(string groupname, Group parentgroup = null, string chatcolor = "255,255,255", string permissions = null)
{ {
Name = groupname; Name = groupname;
@ -162,21 +184,21 @@ namespace TShockAPI
Permissions = permissions; Permissions = permissions;
} }
/// <summary> /// <summary>
/// Checks to see if a group has a specified permission. /// Checks to see if a group has a specified permission.
/// </summary> /// </summary>
/// <param name="permission">The permission to check.</param> /// <param name="permission">The permission to check.</param>
/// <returns>Returns true if the user has that permission.</returns> /// <returns>True if the group has that permission.</returns>
public virtual bool HasPermission(string permission) public virtual bool HasPermission(string permission)
{ {
bool negated = false; bool negated = false;
if (String.IsNullOrEmpty(permission) || (RealHasPermission(permission, ref negated) && !negated)) if (String.IsNullOrEmpty(permission) || (RealHasPermission(permission, ref negated) && !negated))
{ {
return true; return true;
} }
if (negated) if (negated)
return false; return false;
string[] nodes = permission.Split('.'); string[] nodes = permission.Split('.');
for (int i = nodes.Length - 1; i >= 0; i--) for (int i = nodes.Length - 1; i >= 0; i--)
@ -189,37 +211,37 @@ namespace TShockAPI
} }
return false; return false;
} }
private bool RealHasPermission(string permission, ref bool negated) private bool RealHasPermission(string permission, ref bool negated)
{ {
negated = false; negated = false;
if (string.IsNullOrEmpty(permission)) if (string.IsNullOrEmpty(permission))
return true; return true;
var cur = this; var cur = this;
var traversed = new List<Group>(); var traversed = new List<Group>();
while (cur != null) while (cur != null)
{ {
if (cur.negatedpermissions.Contains(permission)) if (cur.negatedpermissions.Contains(permission))
{ {
negated = true; negated = true;
return false; return false;
} }
if (cur.permissions.Contains(permission)) if (cur.permissions.Contains(permission))
return true; return true;
if (traversed.Contains(cur)) if (traversed.Contains(cur))
{ {
throw new InvalidOperationException("Infinite group parenting ({0})".SFormat(cur.Name)); throw new InvalidOperationException("Infinite group parenting ({0})".SFormat(cur.Name));
} }
traversed.Add(cur); traversed.Add(cur);
cur = cur.Parent; cur = cur.Parent;
} }
return false; return false;
} }
/// <summary> /// <summary>
/// Adds a permission to the list of negated permissions. /// Adds a permission to the list of negated permissions.
/// </summary> /// </summary>
/// <param name="permission">The permission to negate.</param> /// <param name="permission">The permission to negate.</param>
public void NegatePermission(string permission) public void NegatePermission(string permission)
{ {
// Avoid duplicates // Avoid duplicates
@ -230,10 +252,10 @@ namespace TShockAPI
} }
} }
/// <summary> /// <summary>
/// Adds a permission to the list of permissions. /// Adds a permission to the list of permissions.
/// </summary> /// </summary>
/// <param name="permission">The permission to add.</param> /// <param name="permission">The permission to add.</param>
public void AddPermission(string permission) public void AddPermission(string permission)
{ {
if (permission.StartsWith("!")) if (permission.StartsWith("!"))
@ -249,11 +271,11 @@ namespace TShockAPI
} }
} }
/// <summary> /// <summary>
/// Clears the permission list and sets it to the list provided, /// Clears the permission list and sets it to the list provided,
/// will parse "!permssion" and add it to the negated permissions. /// will parse "!permssion" and add it to the negated permissions.
/// </summary> /// </summary>
/// <param name="permission"></param> /// <param name="permission">The new list of permissions to associate with the group.</param>
public void SetPermission(List<string> permission) public void SetPermission(List<string> permission)
{ {
permissions.Clear(); permissions.Clear();
@ -261,11 +283,11 @@ namespace TShockAPI
permission.ForEach(p => AddPermission(p)); permission.ForEach(p => AddPermission(p));
} }
/// <summary> /// <summary>
/// Will remove a permission from the respective list, /// Will remove a permission from the respective list,
/// where "!permission" will remove a negated permission. /// where "!permission" will remove a negated permission.
/// </summary> /// </summary>
/// <param name="permission"></param> /// <param name="permission"></param>
public void RemovePermission(string permission) public void RemovePermission(string permission)
{ {
if (permission.StartsWith("!")) if (permission.StartsWith("!"))
@ -277,9 +299,9 @@ namespace TShockAPI
} }
/// <summary> /// <summary>
/// Assigns all fields of this instance to another. /// Assigns all fields of this instance to another.
/// </summary> /// </summary>
/// <param name="otherGroup">The other instance.</param> /// <param name="otherGroup">The other instance.</param>
public void AssignTo(Group otherGroup) public void AssignTo(Group otherGroup)
{ {
otherGroup.Name = Name; otherGroup.Name = Name;
@ -292,35 +314,44 @@ namespace TShockAPI
otherGroup.Permissions = Permissions; otherGroup.Permissions = Permissions;
} }
public override string ToString() { public override string ToString()
{
return this.Name; return this.Name;
} }
} }
/// <summary> /// <summary>
/// This class is the SuperAdminGroup, which has access to everything. /// This class is the SuperAdminGroup, which has access to everything.
/// </summary> /// </summary>
public class SuperAdminGroup : Group public class SuperAdminGroup : Group
{ {
/// <summary>
/// The superadmin class has every permission, represented by '*'.
/// </summary>
public override List<string> TotalPermissions public override List<string> TotalPermissions
{ {
get { return new List<string> { "*" }; } get { return new List<string> { "*" }; }
} }
/// <summary>
/// Initializes a new instance of the SuperAdminGroup class with the configured parameters.
/// Those can be changed in the config file.
/// </summary>
public SuperAdminGroup() public SuperAdminGroup()
: base("superadmin") : base("superadmin")
{ {
R = (byte) TShock.Config.SuperAdminChatRGB[0]; R = (byte)TShock.Config.SuperAdminChatRGB[0];
G = (byte) TShock.Config.SuperAdminChatRGB[1]; G = (byte)TShock.Config.SuperAdminChatRGB[1];
B = (byte) TShock.Config.SuperAdminChatRGB[2]; B = (byte)TShock.Config.SuperAdminChatRGB[2];
Prefix = TShock.Config.SuperAdminChatPrefix; Prefix = TShock.Config.SuperAdminChatPrefix;
Suffix = TShock.Config.SuperAdminChatSuffix; Suffix = TShock.Config.SuperAdminChatSuffix;
} }
/// <summary> /// <summary>
/// Override to allow access to everything. /// Override to allow access to everything.
/// </summary> /// </summary>
/// <param name="permission">The permission</param> /// <param name="permission">The permission</param>
/// <returns>True</returns> /// <returns>True</returns>
public override bool HasPermission(string permission) public override bool HasPermission(string permission)
{ {
return true; return true;

View file

@ -21,66 +21,214 @@ using System.ComponentModel;
namespace TShockAPI.Hooks namespace TShockAPI.Hooks
{ {
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerPostLogin"/> event.
/// </summary>
public class PlayerPostLoginEventArgs public class PlayerPostLoginEventArgs
{ {
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; } public TSPlayer Player { get; set; }
/// <summary>
/// Initializes a new instance of the PlayerPostLoginEventArgs class.
/// </summary>
/// <param name="ply">The player who fired the event.</param>
public PlayerPostLoginEventArgs(TSPlayer ply) public PlayerPostLoginEventArgs(TSPlayer ply)
{ {
Player = ply; Player = ply;
} }
} }
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerPreLogin"/> event.
/// </summary>
public class PlayerPreLoginEventArgs : HandledEventArgs public class PlayerPreLoginEventArgs : HandledEventArgs
{ {
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; } public TSPlayer Player { get; set; }
/// <summary>
/// The player's login name.
/// </summary>
public string LoginName { get; set; } public string LoginName { get; set; }
/// <summary>
/// The player's raw password.
/// </summary>
public string Password { get; set; } public string Password { get; set; }
} }
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerLogout"/> event.
/// </summary>
public class PlayerLogoutEventArgs public class PlayerLogoutEventArgs
{ {
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; } public TSPlayer Player { get; set; }
/// <summary>
/// Initializes a new instance of the PlayerLogoutEventArgs class.
/// </summary>
/// <param name="player">The player who fired the event.</param>
public PlayerLogoutEventArgs(TSPlayer player) public PlayerLogoutEventArgs(TSPlayer player)
{ {
Player = player; Player = player;
} }
} }
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerCommand"/> event.
/// </summary>
public class PlayerCommandEventArgs : HandledEventArgs public class PlayerCommandEventArgs : HandledEventArgs
{ {
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; } public TSPlayer Player { get; set; }
/// <summary>
/// The command's name that follows the <see cref="Commands.Specifier"/>.
/// </summary>
public string CommandName { get; set; } public string CommandName { get; set; }
/// <summary>
/// The command's full text.
/// </summary>
public string CommandText { get; set; } public string CommandText { get; set; }
/// <summary>
/// The command's parameters extracted from <see cref="CommandText"/>.
/// </summary>
public List<string> Parameters { get; set; } public List<string> Parameters { get; set; }
/// <summary>
/// The full list of server commands.
/// </summary>
public IEnumerable<Command> CommandList { get; set; } public IEnumerable<Command> CommandList { get; set; }
/// <summary>
/// The prefix used to send the command (either <see cref="Commands.Specifier"/> or <see cref="Commands.SilentSpecifier"/>).
/// </summary>
public string CommandPrefix { get; set; } public string CommandPrefix { get; set; }
} }
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerChat"/> event.
/// </summary>
public class PlayerChatEventArgs : HandledEventArgs public class PlayerChatEventArgs : HandledEventArgs
{ {
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; } public TSPlayer Player { get; set; }
/// <summary>
/// The raw chat text as received by the server.
/// </summary>
public string RawText { get; set; } public string RawText { get; set; }
/// <summary>
/// The <see cref="RawText"/> string after being formatted by TShock as specified in the config file.
/// </summary>
public string TShockFormattedText { get; set; } public string TShockFormattedText { get; set; }
} }
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerPermission"/> event.
/// </summary>
public class PlayerPermissionEventArgs : HandledEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// Initializes a new instance of the PlayerPermissionEventArgs class.
/// </summary>
/// <param name="player"></param>
public PlayerPermissionEventArgs(TSPlayer player)
{
Player = player;
}
}
/// <summary>
/// A collection of events fired by players that can be hooked to.
/// </summary>
public static class PlayerHooks public static class PlayerHooks
{ {
/// <summary>
/// The delegate of the <see cref="PlayerPostLogin"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerPostLoginD(PlayerPostLoginEventArgs e); public delegate void PlayerPostLoginD(PlayerPostLoginEventArgs e);
/// <summary>
/// Fired by players after they've successfully logged in to a user account.
/// </summary>
public static event PlayerPostLoginD PlayerPostLogin; public static event PlayerPostLoginD PlayerPostLogin;
/// <summary>
/// The delegate of the <see cref="PlayerPreLogin"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerPreLoginD(PlayerPreLoginEventArgs e); public delegate void PlayerPreLoginD(PlayerPreLoginEventArgs e);
/// <summary>
/// Fired by players when sending login credentials to the server.
/// </summary>
public static event PlayerPreLoginD PlayerPreLogin; public static event PlayerPreLoginD PlayerPreLogin;
/// <summary>
/// The delegate of the <see cref="PlayerLogout"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerLogoutD(PlayerLogoutEventArgs e); public delegate void PlayerLogoutD(PlayerLogoutEventArgs e);
/// <summary>
/// Fired by players upon logging out from a user account.
/// </summary>
public static event PlayerLogoutD PlayerLogout; public static event PlayerLogoutD PlayerLogout;
/// <summary>
/// The delegate of the <see cref="PlayerCommand"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerCommandD(PlayerCommandEventArgs e); public delegate void PlayerCommandD(PlayerCommandEventArgs e);
/// <summary>
/// Fired by players when using a command.
/// </summary>
public static event PlayerCommandD PlayerCommand; public static event PlayerCommandD PlayerCommand;
/// <summary>
/// The delegate of the <see cref="PlayerChat"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerChatD(PlayerChatEventArgs e); public delegate void PlayerChatD(PlayerChatEventArgs e);
/// <summary>
/// Fired by players when they send a chat message packet to the server
/// and before it is transmitted to the rest of the players.
/// </summary>
public static event PlayerChatD PlayerChat; public static event PlayerChatD PlayerChat;
/// <summary>
/// The delegate of the <see cref="PlayerPermission"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerPermissionD(PlayerPermissionEventArgs e);
/// <summary>
/// Fired by players every time a permission check involving them occurs.
/// </summary>
public static event PlayerPermissionD PlayerPermission;
/// <summary>
/// Fires the <see cref="PlayerPostLogin"/> event.
/// </summary>
/// <param name="ply">The player firing the event.</param>
public static void OnPlayerPostLogin(TSPlayer ply) public static void OnPlayerPostLogin(TSPlayer ply)
{ {
if (PlayerPostLogin == null) if (PlayerPostLogin == null)
@ -92,6 +240,16 @@ namespace TShockAPI.Hooks
PlayerPostLogin(args); PlayerPostLogin(args);
} }
/// <summary>
/// Fires the <see cref="PlayerCommand"/> event.
/// </summary>
/// <param name="player">The player firing the event.</param>
/// <param name="cmdName">The command name.</param>
/// <param name="cmdText">The raw command text.</param>
/// <param name="args">The command args extracted from the command text.</param>
/// <param name="commands">The list of commands.</param>
/// <param name="cmdPrefix">The command specifier used.</param>
/// <returns>True if the event has been handled.</returns>
public static bool OnPlayerCommand(TSPlayer player, string cmdName, string cmdText, List<string> args, ref IEnumerable<Command> commands, string cmdPrefix) public static bool OnPlayerCommand(TSPlayer player, string cmdName, string cmdText, List<string> args, ref IEnumerable<Command> commands, string cmdPrefix)
{ {
if (PlayerCommand == null) if (PlayerCommand == null)
@ -111,6 +269,13 @@ namespace TShockAPI.Hooks
return playerCommandEventArgs.Handled; return playerCommandEventArgs.Handled;
} }
/// <summary>
/// Fires the <see cref="PlayerPreLogin"/> event.
/// </summary>
/// <param name="ply">The player firing the event.</param>
/// <param name="name">The user name.</param>
/// <param name="pass">The password.</param>
/// <returns>True if the event has been handled.</returns>
public static bool OnPlayerPreLogin(TSPlayer ply, string name, string pass) public static bool OnPlayerPreLogin(TSPlayer ply, string name, string pass)
{ {
if (PlayerPreLogin == null) if (PlayerPreLogin == null)
@ -121,6 +286,10 @@ namespace TShockAPI.Hooks
return args.Handled; return args.Handled;
} }
/// <summary>
/// Fires the <see cref="PlayerLogout"/> event.
/// </summary>
/// <param name="ply">The player firing the event.</param>
public static void OnPlayerLogout(TSPlayer ply) public static void OnPlayerLogout(TSPlayer ply)
{ {
if (PlayerLogout == null) if (PlayerLogout == null)
@ -130,6 +299,12 @@ namespace TShockAPI.Hooks
PlayerLogout(args); PlayerLogout(args);
} }
/// <summary>
/// Fires the <see cref="PlayerChat"/> event.
/// </summary>
/// <param name="ply">The player firing the event.</param>
/// <param name="rawtext">The raw chat text sent by the player.</param>
/// <param name="tshockText">The chat text after being formatted.</param>
public static void OnPlayerChat(TSPlayer ply, string rawtext, ref string tshockText) public static void OnPlayerChat(TSPlayer ply, string rawtext, ref string tshockText)
{ {
if (PlayerChat == null) if (PlayerChat == null)
@ -139,5 +314,20 @@ namespace TShockAPI.Hooks
PlayerChat(args); PlayerChat(args);
tshockText = args.TShockFormattedText; tshockText = args.TShockFormattedText;
} }
/// <summary>
/// Fires the <see cref="PlayerPermission"/> event.
/// </summary>
/// <param name="player">The player firing the event.</param>
/// <returns>True if the event has been handled.</returns>
public static bool OnPlayerPermission(TSPlayer player)
{
if (PlayerPermission == null)
return false;
var args = new PlayerPermissionEventArgs(player);
PlayerPermission(args);
return args.Handled;
}
} }
} }

View file

@ -26,6 +26,7 @@ using System.Timers;
using Terraria; using Terraria;
using Terraria.ID; using Terraria.ID;
using TShockAPI.DB; using TShockAPI.DB;
using TShockAPI.Hooks;
using TShockAPI.Net; using TShockAPI.Net;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
@ -430,11 +431,11 @@ namespace TShockAPI
} }
try try
{ {
if ((tempGroup != null && tempGroup.HasPermission(Permissions.bypassssc)) || Group.HasPermission(Permissions.bypassssc)) if (HasPermission(Permissions.bypassssc))
{ {
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + User.Name); // Debug Code TShock.Log.ConsoleInfo("Skipping SSC Backup for " + User.Name); // Debug Code
return true; return true;
} }
PlayerData.CopyCharacter(this); PlayerData.CopyCharacter(this);
TShock.CharacterDB.InsertPlayerData(this); TShock.CharacterDB.InsertPlayerData(this);
return true; return true;
@ -875,22 +876,22 @@ namespace TShockAPI
} }
} }
/* /*
* Calling new StackTrace() is incredibly expensive, and must be disabled * Calling new StackTrace() is incredibly expensive, and must be disabled
* in release builds. Use a conditional call instead. * in release builds. Use a conditional call instead.
*/ */
LogStackFrame(); LogStackFrame();
} }
[Conditional("DEBUG")] [Conditional("DEBUG")]
private void LogStackFrame() private void LogStackFrame()
{ {
var trace = new StackTrace(); var trace = new StackTrace();
StackFrame frame = null; StackFrame frame = null;
frame = trace.GetFrame(1); frame = trace.GetFrame(1);
if (frame != null && frame.GetMethod().DeclaringType != null) if (frame != null && frame.GetMethod().DeclaringType != null)
TShock.Log.Debug(frame.GetMethod().DeclaringType.Name + " called Disable()."); TShock.Log.Debug(frame.GetMethod().DeclaringType.Name + " called Disable().");
} }
public virtual void Whoopie(object time) public virtual void Whoopie(object time)
{ {
@ -954,6 +955,19 @@ namespace TShockAPI
AwaitingResponse.Add(name, callback); AwaitingResponse.Add(name, callback);
} }
/// <summary>
/// Checks to see if a player or its associated group/temporary group has a specified permission.
/// </summary>
/// <param name="permission">The permission to check.</param>
/// <returns>True if the player has that permission.</returns>
public bool HasPermission(string permission)
{
if (PlayerHooks.OnPlayerPermission(this))
return true;
return (tempGroup != null && tempGroup.HasPermission(permission)) || Group.HasPermission(permission);
}
} }
public class TSRestPlayer : TSPlayer public class TSRestPlayer : TSPlayer

View file

@ -989,7 +989,7 @@ namespace TShockAPI
string check = "none"; string check = "none";
foreach (Item item in player.TPlayer.inventory) foreach (Item item in player.TPlayer.inventory)
{ {
if (!player.Group.HasPermission(Permissions.ignorestackhackdetection) && (item.stack > item.maxStack || item.stack < 0) && if (!player.HasPermission(Permissions.ignorestackhackdetection) && (item.stack > item.maxStack || item.stack < 0) &&
item.type != 0) item.type != 0)
{ {
check = "Remove item " + item.name + " (" + item.stack + ") exceeds max stack of " + item.maxStack; check = "Remove item " + item.name + " (" + item.stack + ") exceeds max stack of " + item.maxStack;
@ -1334,7 +1334,7 @@ namespace TShockAPI
} }
else else
{ {
if (!tsplr.Group.HasPermission(Permissions.canchat)) if (!tsplr.HasPermission(Permissions.canchat))
{ {
args.Handled = true; args.Handled = true;
} }
@ -1652,7 +1652,7 @@ namespace TShockAPI
/// <returns>bool - True if the player should not be able to modify a tile.</returns> /// <returns>bool - True if the player should not be able to modify a tile.</returns>
public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY, short tileType, GetDataHandlers.EditAction actionType) public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY, short tileType, GetDataHandlers.EditAction actionType)
{ {
if (!player.Group.HasPermission(Permissions.canbuild)) if (!player.HasPermission(Permissions.canbuild))
{ {
if (TShock.Config.AllowIce && actionType != GetDataHandlers.EditAction.PlaceTile) if (TShock.Config.AllowIce && actionType != GetDataHandlers.EditAction.PlaceTile)
{ {
@ -1687,7 +1687,7 @@ namespace TShockAPI
return true; return true;
} }
if (!player.Group.HasPermission(Permissions.editregion) && !Regions.CanBuild(tileX, tileY, player) && if (!player.HasPermission(Permissions.editregion) && !Regions.CanBuild(tileX, tileY, player) &&
Regions.InArea(tileX, tileY)) Regions.InArea(tileX, tileY))
{ {
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000) if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000)
@ -1700,7 +1700,7 @@ namespace TShockAPI
if (Config.DisableBuild) if (Config.DisableBuild)
{ {
if (!player.Group.HasPermission(Permissions.antibuild)) if (!player.HasPermission(Permissions.antibuild))
{ {
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000) if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000)
{ {
@ -1713,7 +1713,7 @@ namespace TShockAPI
if (Config.SpawnProtection) if (Config.SpawnProtection)
{ {
if (!player.Group.HasPermission(Permissions.editspawn)) if (!player.HasPermission(Permissions.editspawn))
{ {
if (CheckSpawn(tileX, tileY)) if (CheckSpawn(tileX, tileY))
{ {
@ -1737,8 +1737,8 @@ namespace TShockAPI
/// <returns>bool - True if the player should not be able to modify the tile.</returns> /// <returns>bool - True if the player should not be able to modify the tile.</returns>
public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY, bool paint = false) public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY, bool paint = false)
{ {
if ((!paint && !player.Group.HasPermission(Permissions.canbuild)) || if ((!paint && !player.HasPermission(Permissions.canbuild)) ||
(paint && !player.Group.HasPermission(Permissions.canpaint))) (paint && !player.HasPermission(Permissions.canpaint)))
{ {
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000) if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000)
{ {
@ -1755,7 +1755,7 @@ namespace TShockAPI
return true; return true;
} }
if (!player.Group.HasPermission(Permissions.editregion) && !Regions.CanBuild(tileX, tileY, player) && if (!player.HasPermission(Permissions.editregion) && !Regions.CanBuild(tileX, tileY, player) &&
Regions.InArea(tileX, tileY)) Regions.InArea(tileX, tileY))
{ {
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000) if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000)
@ -1768,7 +1768,7 @@ namespace TShockAPI
if (Config.DisableBuild) if (Config.DisableBuild)
{ {
if (!player.Group.HasPermission(Permissions.antibuild)) if (!player.HasPermission(Permissions.antibuild))
{ {
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000) if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000)
{ {
@ -1781,7 +1781,7 @@ namespace TShockAPI
if (Config.SpawnProtection) if (Config.SpawnProtection)
{ {
if (!player.Group.HasPermission(Permissions.editspawn)) if (!player.HasPermission(Permissions.editspawn))
{ {
if (CheckSpawn(tileX, tileY)) if (CheckSpawn(tileX, tileY))
{ {

View file

@ -107,7 +107,7 @@ namespace TShockAPI
NotifyAdministrator(TSPlayer.Server, changes); NotifyAdministrator(TSPlayer.Server, changes);
foreach (TSPlayer player in TShock.Players) foreach (TSPlayer player in TShock.Players)
{ {
if (player != null && player.Active && player.Group.HasPermission(Permissions.maintenance)) if (player != null && player.Active && player.HasPermission(Permissions.maintenance))
{ {
NotifyAdministrator(player, changes); NotifyAdministrator(player, changes);
} }

View file

@ -191,7 +191,7 @@ namespace TShockAPI
TSPlayer.Server.SendMessage(log, color); TSPlayer.Server.SendMessage(log, color);
foreach (TSPlayer player in TShock.Players) foreach (TSPlayer player in TShock.Players)
{ {
if (player != null && player != excludedPlayer && player.Active && player.Group.HasPermission(Permissions.logs) && if (player != null && player != excludedPlayer && player.Active && player.HasPermission(Permissions.logs) &&
player.DisplayLogs && TShock.Config.DisableSpewLogs == false) player.DisplayLogs && TShock.Config.DisableSpewLogs == false)
player.SendMessage(log, color); player.SendMessage(log, color);
} }
@ -610,7 +610,7 @@ namespace TShockAPI
{ {
if (!player.ConnectionAlive) if (!player.ConnectionAlive)
return true; return true;
if (force || !player.Group.HasPermission(Permissions.immunetokick)) if (force || !player.HasPermission(Permissions.immunetokick))
{ {
string playerName = player.Name; string playerName = player.Name;
player.SilentKickInProgress = silent; player.SilentKickInProgress = silent;
@ -642,7 +642,7 @@ namespace TShockAPI
{ {
if (!player.ConnectionAlive) if (!player.ConnectionAlive)
return true; return true;
if (force || !player.Group.HasPermission(Permissions.immunetoban)) if (force || !player.HasPermission(Permissions.immunetoban))
{ {
string ip = player.IP; string ip = player.IP;
string uuid = player.UUID; string uuid = player.UUID;