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;
foreach (var Permission in Permissions)
{
if (ply.Group.HasPermission(Permission))
if (ply.HasPermission(Permission))
return true;
}
return false;
@ -795,7 +795,7 @@ namespace TShockAPI
if (Main.ServerSideCharacter)
{
if (group.HasPermission(Permissions.bypassssc))
if (args.Player.HasPermission(Permissions.bypassssc))
{
args.Player.IgnoreActionsForClearingTrashCan = false;
}
@ -803,10 +803,10 @@ namespace TShockAPI
}
args.Player.LoginFailsBySsi = false;
if (group.HasPermission(Permissions.ignorestackhackdetection))
if (args.Player.HasPermission(Permissions.ignorestackhackdetection))
args.Player.IgnoreActionsForCheating = "none";
if (group.HasPermission(Permissions.usebanneditem))
if (args.Player.HasPermission(Permissions.usebanneditem))
args.Player.IgnoreActionsForDisabledArmor = "none";
args.Player.Group = group;
@ -1381,7 +1381,7 @@ namespace TShockAPI
TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name));
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);
return;
@ -2237,7 +2237,7 @@ namespace TShockAPI
{
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);
else
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tp <player>", Specifier);
@ -2254,7 +2254,7 @@ namespace TShockAPI
else
{
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);
return;
@ -2262,14 +2262,14 @@ namespace TShockAPI
if (args.Player.Teleport(target.TPlayer.position.X, target.TPlayer.position.Y))
{
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);
}
}
}
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.");
return;
@ -2286,7 +2286,7 @@ namespace TShockAPI
{
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.");
return;
@ -2295,22 +2295,22 @@ namespace TShockAPI
var target = players2[0];
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;
if (source.Teleport(target.TPlayer.position.X, target.TPlayer.position.Y))
{
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);
else
source.SendSuccessMessage("{0} teleported you to {1}.", args.Player.Name, target.Name);
}
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);
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);
}
}
@ -2325,13 +2325,13 @@ namespace TShockAPI
else
{
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);
return;
}
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);
return;
@ -2341,16 +2341,16 @@ namespace TShockAPI
{
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);
else
source.SendSuccessMessage("{0} teleported you to {1}.", args.Player.Name, target.Name);
}
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);
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);
}
}
@ -2362,7 +2362,7 @@ namespace TShockAPI
{
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);
else
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}tphere <player>", Specifier);
@ -2375,7 +2375,7 @@ namespace TShockAPI
{
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.");
return;
@ -2500,7 +2500,7 @@ namespace TShockAPI
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 (hasManageWarpPermission)
@ -2603,7 +2603,7 @@ namespace TShockAPI
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}warp hide [name] <true/false>", Specifier);
#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
if (args.Parameters.Count < 3)
@ -3852,7 +3852,7 @@ namespace TShockAPI
{
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);
}
@ -4349,7 +4349,7 @@ namespace TShockAPI
}
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.");
break;
@ -4397,7 +4397,7 @@ namespace TShockAPI
"protect <name> <true/false> - Sets whether the tiles inside the region are protected or not.",
"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.");
PaginationTools.SendPage(
@ -4526,7 +4526,7 @@ namespace TShockAPI
args.Player.SendErrorMessage("Invalid usage, proper usage: {0}who [-i] [pagenumber]", Specifier);
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.");
return;
@ -4658,7 +4658,7 @@ namespace TShockAPI
{
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.");
}
@ -5497,7 +5497,7 @@ namespace TShockAPI
TSPlayer playerToGod;
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!");
return;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1305,7 +1305,7 @@ namespace TShockAPI
args.Player.PlayerData.StoreSlot(slot, type, prefix, stack);
}
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.
args.Player.IgnoreActionsForClearingTrashCan = true;
@ -1329,7 +1329,7 @@ namespace TShockAPI
if (OnPlayerHP(plr, cur, max) || cur <= 0 || max <= 0 || args.Player.IgnoreSSCPackets)
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);
return true;
@ -1358,7 +1358,7 @@ namespace TShockAPI
if (OnPlayerMana(plr, cur, max) || cur < 0 || max < 0 || args.Player.IgnoreSSCPackets)
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);
return true;
@ -1476,17 +1476,17 @@ namespace TShockAPI
if (Main.ServerSideCharacter)
{
if (!group.HasPermission(Permissions.bypassssc))
if (!args.Player.HasPermission(Permissions.bypassssc))
{
args.Player.PlayerData.RestoreCharacter(args.Player);
}
}
args.Player.LoginFailsBySsi = false;
if (group.HasPermission(Permissions.ignorestackhackdetection))
if (args.Player.HasPermission(Permissions.ignorestackhackdetection))
args.Player.IgnoreActionsForCheating = "none";
if (group.HasPermission(Permissions.usebanneditem))
if (args.Player.HasPermission(Permissions.usebanneditem))
args.Player.IgnoreActionsForDisabledArmor = "none";
args.Player.Group = group;
@ -1551,7 +1551,7 @@ namespace TShockAPI
if (Main.ServerSideCharacter)
{
if (group.HasPermission(Permissions.bypassssc))
if (args.Player.HasPermission(Permissions.bypassssc))
{
args.Player.IgnoreActionsForClearingTrashCan = false;
}
@ -1559,10 +1559,10 @@ namespace TShockAPI
}
args.Player.LoginFailsBySsi = false;
if (group.HasPermission(Permissions.ignorestackhackdetection))
if (args.Player.HasPermission(Permissions.ignorestackhackdetection))
args.Player.IgnoreActionsForCheating = "none";
if (group.HasPermission(Permissions.usebanneditem))
if (args.Player.HasPermission(Permissions.usebanneditem))
args.Player.IgnoreActionsForDisabledArmor = "none";
args.Player.Group = group;
@ -1614,13 +1614,13 @@ namespace TShockAPI
return true;
}
if (!args.Player.Group.HasPermission(Permissions.ignorestackhackdetection))
if (!args.Player.HasPermission(Permissions.ignorestackhackdetection))
{
TShock.HackedInventory(args.Player);
}
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);
return true;
@ -1681,7 +1681,7 @@ namespace TShockAPI
isTrapdoor = true;
}
if (args.Player.Group.HasPermission(Permissions.allowclientsideworldedit) && !isTrapdoor)
if (args.Player.HasPermission(Permissions.allowclientsideworldedit) && !isTrapdoor)
return false;
if (OnSendTileSquare(size, tileX, tileY))
@ -2133,7 +2133,7 @@ namespace TShockAPI
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++;
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] &&
!args.Player.Group.HasPermission(Permissions.ignorekilltiledetection))
!args.Player.HasPermission(Permissions.ignorekilltiledetection))
{
args.Player.TileKillThreshold++;
var coords = new Vector2(tileX, tileY);
@ -2235,7 +2235,7 @@ namespace TShockAPI
return true;
}
if (!args.Player.Group.HasPermission(Permissions.ignoreplacetiledetection))
if (!args.Player.HasPermission(Permissions.ignoreplacetiledetection))
{
args.Player.TilePlaceThreshold++;
var coords = new Vector2(x, y);
@ -2437,7 +2437,7 @@ namespace TShockAPI
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
&& !args.TPlayer.tongued)
{
@ -2617,7 +2617,7 @@ namespace TShockAPI
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.RemoveProjectile(ident, owner);
@ -2631,7 +2631,7 @@ namespace TShockAPI
}
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
|| type == ProjectileID.PhantasmalEye
@ -2668,7 +2668,7 @@ namespace TShockAPI
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
{
@ -2831,7 +2831,7 @@ namespace TShockAPI
return true;
}
if (!args.Player.Group.HasPermission(Permissions.ignoreliquidsetdetection))
if (!args.Player.HasPermission(Permissions.ignoreliquidsetdetection))
{
args.Player.TileLiquidThreshold++;
}
@ -3149,7 +3149,7 @@ namespace TShockAPI
if (OnUpdateNPCHome(id, x, y, homeless))
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.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY,
@ -3281,7 +3281,7 @@ namespace TShockAPI
Item item = new Item();
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);
return true;
@ -3338,7 +3338,7 @@ namespace TShockAPI
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)
{
@ -3404,7 +3404,7 @@ namespace TShockAPI
if (Main.npc[id] == null)
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)
{
@ -3425,7 +3425,7 @@ namespace TShockAPI
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.SendData(PacketTypes.NpcUpdate, "", id);
@ -3588,12 +3588,12 @@ namespace TShockAPI
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.");
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.");
return true;
@ -3670,7 +3670,7 @@ namespace TShockAPI
return true;
}
if (!args.Player.Group.HasPermission(Permissions.ignorepaintdetection))
if (!args.Player.HasPermission(Permissions.ignorepaintdetection))
{
args.Player.PaintThreshold++;
}
@ -3714,7 +3714,7 @@ namespace TShockAPI
return true;
}
if (!args.Player.Group.HasPermission(Permissions.ignorepaintdetection))
if (!args.Player.HasPermission(Permissions.ignorepaintdetection))
{
args.Player.PaintThreshold++;
}
@ -3753,7 +3753,7 @@ namespace TShockAPI
}
//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.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y);
@ -3774,7 +3774,7 @@ namespace TShockAPI
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.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y);

View file

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

View file

@ -21,66 +21,214 @@ using System.ComponentModel;
namespace TShockAPI.Hooks
{
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerPostLogin"/> event.
/// </summary>
public class PlayerPostLoginEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
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)
{
Player = ply;
}
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerPreLogin"/> event.
/// </summary>
public class PlayerPreLoginEventArgs : HandledEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// The player's login name.
/// </summary>
public string LoginName { get; set; }
/// <summary>
/// The player's raw password.
/// </summary>
public string Password { get; set; }
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerLogout"/> event.
/// </summary>
public class PlayerLogoutEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
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)
{
Player = player;
}
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerCommand"/> event.
/// </summary>
public class PlayerCommandEventArgs : HandledEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// The command's name that follows the <see cref="Commands.Specifier"/>.
/// </summary>
public string CommandName { get; set; }
/// <summary>
/// The command's full text.
/// </summary>
public string CommandText { get; set; }
/// <summary>
/// The command's parameters extracted from <see cref="CommandText"/>.
/// </summary>
public List<string> Parameters { get; set; }
/// <summary>
/// The full list of server commands.
/// </summary>
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; }
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerChat"/> event.
/// </summary>
public class PlayerChatEventArgs : HandledEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// The raw chat text as received by the server.
/// </summary>
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; }
}
/// <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
{
/// <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);
/// <summary>
/// Fired by players after they've successfully logged in to a user account.
/// </summary>
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);
/// <summary>
/// Fired by players when sending login credentials to the server.
/// </summary>
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);
/// <summary>
/// Fired by players upon logging out from a user account.
/// </summary>
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);
/// <summary>
/// Fired by players when using a command.
/// </summary>
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);
/// <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;
/// <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)
{
if (PlayerPostLogin == null)
@ -92,6 +240,16 @@ namespace TShockAPI.Hooks
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)
{
if (PlayerCommand == null)
@ -111,6 +269,13 @@ namespace TShockAPI.Hooks
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)
{
if (PlayerPreLogin == null)
@ -121,6 +286,10 @@ namespace TShockAPI.Hooks
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)
{
if (PlayerLogout == null)
@ -130,6 +299,12 @@ namespace TShockAPI.Hooks
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)
{
if (PlayerChat == null)
@ -139,5 +314,20 @@ namespace TShockAPI.Hooks
PlayerChat(args);
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.ID;
using TShockAPI.DB;
using TShockAPI.Hooks;
using TShockAPI.Net;
using Timer = System.Timers.Timer;
@ -430,11 +431,11 @@ namespace TShockAPI
}
try
{
if ((tempGroup != null && tempGroup.HasPermission(Permissions.bypassssc)) || Group.HasPermission(Permissions.bypassssc))
{
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + User.Name); // Debug Code
return true;
}
if (HasPermission(Permissions.bypassssc))
{
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + User.Name); // Debug Code
return true;
}
PlayerData.CopyCharacter(this);
TShock.CharacterDB.InsertPlayerData(this);
return true;
@ -875,22 +876,22 @@ namespace TShockAPI
}
}
/*
* Calling new StackTrace() is incredibly expensive, and must be disabled
* in release builds. Use a conditional call instead.
*/
LogStackFrame();
/*
* Calling new StackTrace() is incredibly expensive, and must be disabled
* in release builds. Use a conditional call instead.
*/
LogStackFrame();
}
[Conditional("DEBUG")]
private void LogStackFrame()
{
var trace = new StackTrace();
StackFrame frame = null;
frame = trace.GetFrame(1);
if (frame != null && frame.GetMethod().DeclaringType != null)
TShock.Log.Debug(frame.GetMethod().DeclaringType.Name + " called Disable().");
}
[Conditional("DEBUG")]
private void LogStackFrame()
{
var trace = new StackTrace();
StackFrame frame = null;
frame = trace.GetFrame(1);
if (frame != null && frame.GetMethod().DeclaringType != null)
TShock.Log.Debug(frame.GetMethod().DeclaringType.Name + " called Disable().");
}
public virtual void Whoopie(object time)
{
@ -954,6 +955,19 @@ namespace TShockAPI
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

View file

@ -989,7 +989,7 @@ namespace TShockAPI
string check = "none";
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)
{
check = "Remove item " + item.name + " (" + item.stack + ") exceeds max stack of " + item.maxStack;
@ -1334,7 +1334,7 @@ namespace TShockAPI
}
else
{
if (!tsplr.Group.HasPermission(Permissions.canchat))
if (!tsplr.HasPermission(Permissions.canchat))
{
args.Handled = true;
}
@ -1652,7 +1652,7 @@ namespace TShockAPI
/// <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)
{
if (!player.Group.HasPermission(Permissions.canbuild))
if (!player.HasPermission(Permissions.canbuild))
{
if (TShock.Config.AllowIce && actionType != GetDataHandlers.EditAction.PlaceTile)
{
@ -1687,7 +1687,7 @@ namespace TShockAPI
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))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000)
@ -1700,7 +1700,7 @@ namespace TShockAPI
if (Config.DisableBuild)
{
if (!player.Group.HasPermission(Permissions.antibuild))
if (!player.HasPermission(Permissions.antibuild))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000)
{
@ -1713,7 +1713,7 @@ namespace TShockAPI
if (Config.SpawnProtection)
{
if (!player.Group.HasPermission(Permissions.editspawn))
if (!player.HasPermission(Permissions.editspawn))
{
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>
public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY, bool paint = false)
{
if ((!paint && !player.Group.HasPermission(Permissions.canbuild)) ||
(paint && !player.Group.HasPermission(Permissions.canpaint)))
if ((!paint && !player.HasPermission(Permissions.canbuild)) ||
(paint && !player.HasPermission(Permissions.canpaint)))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000)
{
@ -1755,7 +1755,7 @@ namespace TShockAPI
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))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000)
@ -1768,7 +1768,7 @@ namespace TShockAPI
if (Config.DisableBuild)
{
if (!player.Group.HasPermission(Permissions.antibuild))
if (!player.HasPermission(Permissions.antibuild))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000)
{
@ -1781,7 +1781,7 @@ namespace TShockAPI
if (Config.SpawnProtection)
{
if (!player.Group.HasPermission(Permissions.editspawn))
if (!player.HasPermission(Permissions.editspawn))
{
if (CheckSpawn(tileX, tileY))
{

View file

@ -107,7 +107,7 @@ namespace TShockAPI
NotifyAdministrator(TSPlayer.Server, changes);
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);
}

View file

@ -191,7 +191,7 @@ namespace TShockAPI
TSPlayer.Server.SendMessage(log, color);
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.SendMessage(log, color);
}
@ -610,7 +610,7 @@ namespace TShockAPI
{
if (!player.ConnectionAlive)
return true;
if (force || !player.Group.HasPermission(Permissions.immunetokick))
if (force || !player.HasPermission(Permissions.immunetokick))
{
string playerName = player.Name;
player.SilentKickInProgress = silent;
@ -642,7 +642,7 @@ namespace TShockAPI
{
if (!player.ConnectionAlive)
return true;
if (force || !player.Group.HasPermission(Permissions.immunetoban))
if (force || !player.HasPermission(Permissions.immunetoban))
{
string ip = player.IP;
string uuid = player.UUID;