Merge branch 'general-devel' of github.com:NyxStudios/TShock into general-devel

This commit is contained in:
Tyler Watson 2016-01-17 03:38:01 +10:00
commit 8ce3e4933e
17 changed files with 1058 additions and 799 deletions

View file

@ -2,6 +2,11 @@
This is the rolling changelog for TShock for Terraria. Use past tense when adding new entries; sign your name off when you add or change something. This should primarily be things like user changes, not necessarily codebase changes unless it's really relevant or large. This is the rolling changelog for TShock for Terraria. Use past tense when adding new entries; sign your name off when you add or change something. This should primarily be things like user changes, not necessarily codebase changes unless it's really relevant or large.
## Upcoming Changes
* Fixed character styles/gender not being saved properly on first login while SSC is on (@WhiteXZ)
* Added a PlayerPermission hook fired whenever a permission check involving said player occurs (when the new TSPlayer.HasPermission method is called) (@Enerdy)
## TShock 4.3.12 ## TShock 4.3.12
* Fixed issues with TSPlayer.SetTeam not working (@WhiteXZ) * Fixed issues with TSPlayer.SetTeam not working (@WhiteXZ)
@ -16,7 +21,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
## TShock 4.3.11 ## TShock 4.3.11
* This release is actuall 4.3.10, but was ticked extra due to a version issue on gen-dev prior to master push. * This release is actually 4.3.10, but was ticked extra due to a version issue on gen-dev prior to master push.
## TShock 4.3.10 ## TShock 4.3.10

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

@ -96,7 +96,7 @@ namespace TShockAPI.DB
playerData.extraSlot = reader.Get<int>("extraSlot"); playerData.extraSlot = reader.Get<int>("extraSlot");
playerData.spawnX = reader.Get<int>("spawnX"); playerData.spawnX = reader.Get<int>("spawnX");
playerData.spawnY = reader.Get<int>("spawnY"); playerData.spawnY = reader.Get<int>("spawnY");
playerData.skinVariant = reader.Get<int>("skinVariant"); playerData.skinVariant = reader.Get<int?>("skinVariant");
playerData.hair = reader.Get<int?>("hair"); playerData.hair = reader.Get<int?>("hair");
playerData.hairDye = (byte)reader.Get<int>("hairDye"); playerData.hairDye = (byte)reader.Get<int>("hairDye");
playerData.hairColor = TShock.Utils.DecodeColor(reader.Get<int?>("hairColor")); playerData.hairColor = TShock.Utils.DecodeColor(reader.Get<int?>("hairColor"));
@ -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,221 @@ 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>
/// The permission being checked.
/// </summary>
public string Permission { get; set; }
/// <summary>
/// Initializes a new instance of the PlayerPermissionEventArgs class.
/// </summary>
/// <param name="player">The player who fired the event.</param>
/// <param name="permission">The permission being checked.</param>
public PlayerPermissionEventArgs(TSPlayer player, string permission)
{
Player = player;
Permission = permission;
}
}
/// <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 +247,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 +276,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 +293,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 +306,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 +321,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, string permission)
{
if (PlayerPermission == null)
return false;
var args = new PlayerPermissionEventArgs(player, permission);
PlayerPermission(args);
return args.Handled;
}
} }
} }

411
TShockAPI/PlayerData.cs Normal file
View file

@ -0,0 +1,411 @@
using Terraria;
using TShockAPI;
public class PlayerData
{
public NetItem[] inventory = new NetItem[NetItem.MaxInventory];
public int health = TShock.ServerSideCharacterConfig.StartingHealth;
public int maxHealth = TShock.ServerSideCharacterConfig.StartingHealth;
public int mana = TShock.ServerSideCharacterConfig.StartingMana;
public int maxMana = TShock.ServerSideCharacterConfig.StartingMana;
public bool exists;
public int spawnX = -1;
public int spawnY = -1;
public int? extraSlot;
public int? skinVariant;
public int? hair;
public byte hairDye;
public Color? hairColor;
public Color? pantsColor;
public Color? shirtColor;
public Color? underShirtColor;
public Color? shoeColor;
public Color? skinColor;
public Color? eyeColor;
public bool[] hideVisuals;
public int questsCompleted;
public PlayerData(TSPlayer player)
{
for (int i = 0; i < NetItem.MaxInventory; i++)
{
this.inventory[i] = new NetItem();
}
for (int i = 0; i < TShock.ServerSideCharacterConfig.StartingInventory.Count; i++)
{
var item = TShock.ServerSideCharacterConfig.StartingInventory[i];
StoreSlot(i, item.NetId, item.PrefixId, item.Stack);
}
}
/// <summary>
/// Stores an item at the specific storage slot
/// </summary>
/// <param name="slot"></param>
/// <param name="netID"></param>
/// <param name="prefix"></param>
/// <param name="stack"></param>
public void StoreSlot(int slot, int netID, byte prefix, int stack)
{
if (slot > (this.inventory.Length - 1)) //if the slot is out of range then dont save
{
return;
}
this.inventory[slot] = new NetItem(netID, stack, prefix);
}
/// <summary>
/// Copies a characters data to this object
/// </summary>
/// <param name="player"></param>
public void CopyCharacter(TSPlayer player)
{
this.health = player.TPlayer.statLife > 0 ? player.TPlayer.statLife : 1;
this.maxHealth = player.TPlayer.statLifeMax;
this.mana = player.TPlayer.statMana;
this.maxMana = player.TPlayer.statManaMax;
if (player.sX > 0 && player.sY > 0)
{
this.spawnX = player.sX;
this.spawnY = player.sY;
}
else
{
this.spawnX = player.TPlayer.SpawnX;
this.spawnY = player.TPlayer.SpawnY;
}
extraSlot = player.TPlayer.extraAccessory ? 1 : 0;
this.skinVariant = player.TPlayer.skinVariant;
this.hair = player.TPlayer.hair;
this.hairDye = player.TPlayer.hairDye;
this.hairColor = player.TPlayer.hairColor;
this.pantsColor = player.TPlayer.pantsColor;
this.shirtColor = player.TPlayer.shirtColor;
this.underShirtColor = player.TPlayer.underShirtColor;
this.shoeColor = player.TPlayer.shoeColor;
this.hideVisuals = player.TPlayer.hideVisual;
this.skinColor = player.TPlayer.skinColor;
this.eyeColor = player.TPlayer.eyeColor;
this.questsCompleted = player.TPlayer.anglerQuestsFinished;
Item[] inventory = player.TPlayer.inventory;
Item[] armor = player.TPlayer.armor;
Item[] dye = player.TPlayer.dye;
Item[] miscEqups = player.TPlayer.miscEquips;
Item[] miscDyes = player.TPlayer.miscDyes;
Item[] piggy = player.TPlayer.bank.item;
Item[] safe = player.TPlayer.bank2.item;
Item trash = player.TPlayer.trashItem;
for (int i = 0; i < NetItem.MaxInventory; i++)
{
if (i < NetItem.InventorySlots)
{
//0-58
this.inventory[i] = (NetItem)inventory[i];
}
else if (i < NetItem.InventorySlots + NetItem.ArmorSlots)
{
//59-78
var index = i - NetItem.InventorySlots;
this.inventory[i] = (NetItem)armor[index];
}
else if (i < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots)
{
//79-88
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots);
this.inventory[i] = (NetItem)dye[index];
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots)
{
//89-93
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots);
this.inventory[i] = (NetItem)miscEqups[index];
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots
+ NetItem.MiscDyeSlots)
{
//93-98
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots);
this.inventory[i] = (NetItem)miscDyes[index];
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots +
NetItem.MiscDyeSlots + NetItem.PiggySlots)
{
//98-138
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots + NetItem.MiscDyeSlots);
this.inventory[i] = (NetItem)piggy[index];
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots +
NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots)
{
//138-178
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots + NetItem.MiscDyeSlots + NetItem.PiggySlots);
this.inventory[i] = (NetItem)safe[index];
}
else
{
//179
this.inventory[i] = (NetItem)trash;
}
}
}
/// <summary>
/// Restores a player's character to the state stored in the database
/// </summary>
/// <param name="player"></param>
public void RestoreCharacter(TSPlayer player)
{
// Start ignoring SSC-related packets! This is critical so that we don't send or receive dirty data!
player.IgnoreSSCPackets = true;
player.TPlayer.statLife = this.health;
player.TPlayer.statLifeMax = this.maxHealth;
player.TPlayer.statMana = this.maxMana;
player.TPlayer.statManaMax = this.maxMana;
player.TPlayer.SpawnX = this.spawnX;
player.TPlayer.SpawnY = this.spawnY;
player.sX = this.spawnX;
player.sY = this.spawnY;
player.TPlayer.hairDye = this.hairDye;
player.TPlayer.anglerQuestsFinished = this.questsCompleted;
if (extraSlot != null)
player.TPlayer.extraAccessory = extraSlot.Value == 1 ? true : false;
if (this.skinVariant != null)
player.TPlayer.skinVariant = this.skinVariant.Value;
if (this.hair != null)
player.TPlayer.hair = this.hair.Value;
if (this.hairColor != null)
player.TPlayer.hairColor = this.hairColor.Value;
if (this.pantsColor != null)
player.TPlayer.pantsColor = this.pantsColor.Value;
if (this.shirtColor != null)
player.TPlayer.shirtColor = this.shirtColor.Value;
if (this.underShirtColor != null)
player.TPlayer.underShirtColor = this.underShirtColor.Value;
if (this.shoeColor != null)
player.TPlayer.shoeColor = this.shoeColor.Value;
if (this.skinColor != null)
player.TPlayer.skinColor = this.skinColor.Value;
if (this.eyeColor != null)
player.TPlayer.eyeColor = this.eyeColor.Value;
if (this.hideVisuals != null)
player.TPlayer.hideVisual = this.hideVisuals;
else
player.TPlayer.hideVisual = new bool[player.TPlayer.hideVisual.Length];
for (int i = 0; i < NetItem.MaxInventory; i++)
{
if (i < NetItem.InventorySlots)
{
//0-58
player.TPlayer.inventory[i].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.inventory[i].netID != 0)
{
player.TPlayer.inventory[i].stack = this.inventory[i].Stack;
player.TPlayer.inventory[i].prefix = this.inventory[i].PrefixId;
}
}
else if (i < NetItem.InventorySlots + NetItem.ArmorSlots)
{
//59-78
var index = i - NetItem.InventorySlots;
player.TPlayer.armor[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.armor[index].netID != 0)
{
player.TPlayer.armor[index].stack = this.inventory[i].Stack;
player.TPlayer.armor[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots)
{
//79-88
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots);
player.TPlayer.dye[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.dye[index].netID != 0)
{
player.TPlayer.dye[index].stack = this.inventory[i].Stack;
player.TPlayer.dye[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots)
{
//89-93
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots);
player.TPlayer.miscEquips[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.miscEquips[index].netID != 0)
{
player.TPlayer.miscEquips[index].stack = this.inventory[i].Stack;
player.TPlayer.miscEquips[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots
+ NetItem.MiscDyeSlots)
{
//93-98
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots);
player.TPlayer.miscDyes[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.miscDyes[index].netID != 0)
{
player.TPlayer.miscDyes[index].stack = this.inventory[i].Stack;
player.TPlayer.miscDyes[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots +
NetItem.MiscDyeSlots + NetItem.PiggySlots)
{
//98-138
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots + NetItem.MiscDyeSlots);
player.TPlayer.bank.item[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.bank.item[index].netID != 0)
{
player.TPlayer.bank.item[index].stack = this.inventory[i].Stack;
player.TPlayer.bank.item[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots +
NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots)
{
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots + NetItem.MiscDyeSlots + NetItem.PiggySlots);
player.TPlayer.bank2.item[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.bank2.item[index].netID != 0)
{
player.TPlayer.bank2.item[index].stack = this.inventory[i].Stack;
player.TPlayer.bank2.item[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else
{
player.TPlayer.trashItem.netDefaults(this.inventory[i].NetId);
if (player.TPlayer.trashItem.netID != 0)
{
player.TPlayer.trashItem.stack = this.inventory[i].Stack;
player.TPlayer.trashItem.prefix = (byte)this.inventory[i].PrefixId;
}
}
}
float slot = 0f;
for (int k = 0; k < NetItem.InventorySlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].inventory[k].name, player.Index, slot, (float)Main.player[player.Index].inventory[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.ArmorSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[k].name, player.Index, slot, (float)Main.player[player.Index].armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.DyeSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[k].name, player.Index, slot, (float)Main.player[player.Index].dye[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.MiscEquipSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].miscEquips[k].name, player.Index, slot, (float)Main.player[player.Index].miscEquips[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.MiscDyeSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].miscDyes[k].name, player.Index, slot, (float)Main.player[player.Index].miscDyes[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.PiggySlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].bank.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank.item[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.SafeSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].bank2.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank2.item[k].prefix);
slot++;
}
NetMessage.SendData(5, -1, -1, Main.player[player.Index].trashItem.name, player.Index, slot, (float)Main.player[player.Index].trashItem.prefix);
NetMessage.SendData(4, -1, -1, player.Name, player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(42, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(16, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
slot = 0f;
for (int k = 0; k < NetItem.InventorySlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].inventory[k].name, player.Index, slot, (float)Main.player[player.Index].inventory[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.ArmorSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[k].name, player.Index, slot, (float)Main.player[player.Index].armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.DyeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[k].name, player.Index, slot, (float)Main.player[player.Index].dye[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.MiscEquipSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].miscEquips[k].name, player.Index, slot, (float)Main.player[player.Index].miscEquips[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.MiscDyeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].miscDyes[k].name, player.Index, slot, (float)Main.player[player.Index].miscDyes[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.PiggySlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].bank.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank.item[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.SafeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].bank2.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank2.item[k].prefix);
slot++;
}
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].trashItem.name, player.Index, slot, (float)Main.player[player.Index].trashItem.prefix);
NetMessage.SendData(4, player.Index, -1, player.Name, player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(42, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(16, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
for (int k = 0; k < 22; k++)
{
player.TPlayer.buffType[k] = 0;
}
NetMessage.SendData(50, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(50, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(76, -1, -1, "", player.Index);
NetMessage.SendData(39, player.Index, -1, "", 400);
}
}

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,22 @@ 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, permission))
return true;
if (tempGroup != null)
return tempGroup.HasPermission(permission);
else
return Group.HasPermission(permission);
}
} }
public class TSRestPlayer : TSPlayer public class TSRestPlayer : TSPlayer
@ -1001,568 +1018,4 @@ namespace TShockAPI
return this.CommandOutput; return this.CommandOutput;
} }
} }
public class TSServerPlayer : TSPlayer
{
public static string AccountName = "ServerConsole";
public TSServerPlayer()
: base("Server")
{
Group = new SuperAdminGroup();
User = new User{Name = AccountName};
}
public override void SendErrorMessage(string msg)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg);
Console.ResetColor();
}
public override void SendInfoMessage(string msg)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(msg);
Console.ResetColor();
}
public override void SendSuccessMessage(string msg)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(msg);
Console.ResetColor();
}
public override void SendWarningMessage(string msg)
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine(msg);
Console.ResetColor();
}
public override void SendMessage(string msg, Color color)
{
SendMessage(msg, color.R, color.G, color.B);
}
public override void SendMessage(string msg, byte red, byte green, byte blue)
{
Console.WriteLine(msg);
}
public void SetFullMoon()
{
Main.dayTime = false;
Main.moonPhase = 0;
Main.time = 0.0;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetBloodMoon(bool bloodMoon)
{
if (bloodMoon)
{
Main.dayTime = false;
Main.bloodMoon = true;
Main.time = 0.0;
}
else
Main.bloodMoon = false;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetFrostMoon(bool snowMoon)
{
if (snowMoon)
{
Main.dayTime = false;
Main.snowMoon = true;
Main.time = 0.0;
}
else
Main.snowMoon = false;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetPumpkinMoon(bool pumpkinMoon)
{
if (pumpkinMoon)
{
Main.dayTime = false;
Main.pumpkinMoon = true;
Main.time = 0.0;
}
else
Main.pumpkinMoon = false;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetEclipse(bool eclipse)
{
if (eclipse)
{
Main.dayTime = Main.eclipse = true;
Main.time = 0.0;
}
else
Main.eclipse = false;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetTime(bool dayTime, double time)
{
Main.dayTime = dayTime;
Main.time = time;
TSPlayer.All.SendData(PacketTypes.TimeSet, "", dayTime ? 1 : 0, (int)time, Main.sunModY, Main.moonModY);
}
public void SpawnNPC(int type, string name, int amount, int startTileX, int startTileY, int tileXRange = 100,
int tileYRange = 50)
{
for (int i = 0; i < amount; i++)
{
int spawnTileX;
int spawnTileY;
TShock.Utils.GetRandomClearTileWithInRange(startTileX, startTileY, tileXRange, tileYRange, out spawnTileX,
out spawnTileY);
int npcid = NPC.NewNPC(spawnTileX*16, spawnTileY*16, type, 0);
// This is for special slimes
Main.npc[npcid].SetDefaults(name);
}
}
public void StrikeNPC(int npcid, int damage, float knockBack, int hitDirection)
{
// Main.rand is thread static.
if (Main.rand == null)
Main.rand = new Random();
Main.npc[npcid].StrikeNPC(damage, knockBack, hitDirection);
NetMessage.SendData((int) PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
}
public void RevertTiles(Dictionary<Vector2, Tile> tiles)
{
// Update Main.Tile first so that when tile sqaure is sent it is correct
foreach (KeyValuePair<Vector2, Tile> entry in tiles)
{
Main.tile[(int) entry.Key.X, (int) entry.Key.Y] = entry.Value;
}
// Send all players updated tile sqaures
foreach (Vector2 coords in tiles.Keys)
{
All.SendTileSquare((int) coords.X, (int) coords.Y, 3);
}
}
}
public class PlayerData
{
public NetItem[] inventory = new NetItem[NetItem.MaxInventory];
public int health = TShock.ServerSideCharacterConfig.StartingHealth;
public int maxHealth = TShock.ServerSideCharacterConfig.StartingHealth;
public int mana = TShock.ServerSideCharacterConfig.StartingMana;
public int maxMana = TShock.ServerSideCharacterConfig.StartingMana;
public bool exists;
public int spawnX= -1;
public int spawnY= -1;
public int? extraSlot;
public int? skinVariant;
public int? hair;
public byte hairDye;
public Color? hairColor;
public Color? pantsColor;
public Color? shirtColor;
public Color? underShirtColor;
public Color? shoeColor;
public Color? skinColor;
public Color? eyeColor;
public bool[] hideVisuals;
public int questsCompleted;
public PlayerData(TSPlayer player)
{
for (int i = 0; i < NetItem.MaxInventory; i++)
{
this.inventory[i] = new NetItem();
}
for (int i = 0; i < TShock.ServerSideCharacterConfig.StartingInventory.Count; i++)
{
var item = TShock.ServerSideCharacterConfig.StartingInventory[i];
StoreSlot(i, item.NetId, item.PrefixId, item.Stack);
}
}
/// <summary>
/// Stores an item at the specific storage slot
/// </summary>
/// <param name="slot"></param>
/// <param name="netID"></param>
/// <param name="prefix"></param>
/// <param name="stack"></param>
public void StoreSlot(int slot, int netID, byte prefix, int stack)
{
if (slot > (this.inventory.Length - 1)) //if the slot is out of range then dont save
{
return;
}
this.inventory[slot] = new NetItem(netID, stack, prefix);
}
/// <summary>
/// Copies a characters data to this object
/// </summary>
/// <param name="player"></param>
public void CopyCharacter(TSPlayer player)
{
this.health = player.TPlayer.statLife > 0 ? player.TPlayer.statLife : 1;
this.maxHealth = player.TPlayer.statLifeMax;
this.mana = player.TPlayer.statMana;
this.maxMana = player.TPlayer.statManaMax;
if (player.sX > 0 && player.sY > 0)
{
this.spawnX = player.sX;
this.spawnY = player.sY;
}
else
{
this.spawnX = player.TPlayer.SpawnX;
this.spawnY = player.TPlayer.SpawnY;
}
extraSlot = player.TPlayer.extraAccessory ? 1 : 0;
this.skinVariant = player.TPlayer.skinVariant;
this.hair = player.TPlayer.hair;
this.hairDye = player.TPlayer.hairDye;
this.hairColor = player.TPlayer.hairColor;
this.pantsColor = player.TPlayer.pantsColor;
this.shirtColor = player.TPlayer.shirtColor;
this.underShirtColor = player.TPlayer.underShirtColor;
this.shoeColor = player.TPlayer.shoeColor;
this.hideVisuals = player.TPlayer.hideVisual;
this.skinColor = player.TPlayer.skinColor;
this.eyeColor = player.TPlayer.eyeColor;
this.questsCompleted = player.TPlayer.anglerQuestsFinished;
Item[] inventory = player.TPlayer.inventory;
Item[] armor = player.TPlayer.armor;
Item[] dye = player.TPlayer.dye;
Item[] miscEqups = player.TPlayer.miscEquips;
Item[] miscDyes = player.TPlayer.miscDyes;
Item[] piggy = player.TPlayer.bank.item;
Item[] safe = player.TPlayer.bank2.item;
Item trash = player.TPlayer.trashItem;
for (int i = 0; i < NetItem.MaxInventory; i++)
{
if (i < NetItem.InventorySlots)
{
//0-58
this.inventory[i] = (NetItem)inventory[i];
}
else if (i < NetItem.InventorySlots + NetItem.ArmorSlots)
{
//59-78
var index = i - NetItem.InventorySlots;
this.inventory[i] = (NetItem)armor[index];
}
else if (i < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots)
{
//79-88
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots);
this.inventory[i] = (NetItem)dye[index];
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots)
{
//89-93
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots);
this.inventory[i] = (NetItem)miscEqups[index];
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots
+ NetItem.MiscDyeSlots)
{
//93-98
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots);
this.inventory[i] = (NetItem)miscDyes[index];
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots +
NetItem.MiscDyeSlots + NetItem.PiggySlots)
{
//98-138
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots + NetItem.MiscDyeSlots);
this.inventory[i] = (NetItem)piggy[index];
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots +
NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots)
{
//138-178
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots + NetItem.MiscDyeSlots + NetItem.PiggySlots);
this.inventory[i] = (NetItem)safe[index];
}
else
{
//179
this.inventory[i] = (NetItem)trash;
}
}
}
/// <summary>
/// Restores a player's character to the state stored in the database
/// </summary>
/// <param name="player"></param>
public void RestoreCharacter(TSPlayer player)
{
// Start ignoring SSC-related packets! This is critical so that we don't send or receive dirty data!
player.IgnoreSSCPackets = true;
player.TPlayer.statLife = this.health;
player.TPlayer.statLifeMax = this.maxHealth;
player.TPlayer.statMana = this.maxMana;
player.TPlayer.statManaMax = this.maxMana;
player.TPlayer.SpawnX = this.spawnX;
player.TPlayer.SpawnY = this.spawnY;
player.sX = this.spawnX;
player.sY = this.spawnY;
player.TPlayer.hairDye = this.hairDye;
player.TPlayer.anglerQuestsFinished = this.questsCompleted;
if (extraSlot != null)
player.TPlayer.extraAccessory = extraSlot.Value == 1 ? true : false;
if (this.skinVariant != null)
player.TPlayer.skinVariant = this.skinVariant.Value;
if (this.hair != null)
player.TPlayer.hair = this.hair.Value;
if (this.hairColor != null)
player.TPlayer.hairColor = this.hairColor.Value;
if (this.pantsColor != null)
player.TPlayer.pantsColor = this.pantsColor.Value;
if (this.shirtColor != null)
player.TPlayer.shirtColor = this.shirtColor.Value;
if (this.underShirtColor != null)
player.TPlayer.underShirtColor = this.underShirtColor.Value;
if (this.shoeColor != null)
player.TPlayer.shoeColor = this.shoeColor.Value;
if (this.skinColor != null)
player.TPlayer.skinColor = this.skinColor.Value;
if (this.eyeColor != null)
player.TPlayer.eyeColor = this.eyeColor.Value;
if (this.hideVisuals != null)
player.TPlayer.hideVisual = this.hideVisuals;
else
player.TPlayer.hideVisual = new bool[player.TPlayer.hideVisual.Length];
for (int i = 0; i < NetItem.MaxInventory; i++)
{
if (i < NetItem.InventorySlots)
{
//0-58
player.TPlayer.inventory[i].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.inventory[i].netID != 0)
{
player.TPlayer.inventory[i].stack = this.inventory[i].Stack;
player.TPlayer.inventory[i].prefix = this.inventory[i].PrefixId;
}
}
else if (i < NetItem.InventorySlots + NetItem.ArmorSlots)
{
//59-78
var index = i - NetItem.InventorySlots;
player.TPlayer.armor[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.armor[index].netID != 0)
{
player.TPlayer.armor[index].stack = this.inventory[i].Stack;
player.TPlayer.armor[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots)
{
//79-88
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots);
player.TPlayer.dye[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.dye[index].netID != 0)
{
player.TPlayer.dye[index].stack = this.inventory[i].Stack;
player.TPlayer.dye[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots)
{
//89-93
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots);
player.TPlayer.miscEquips[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.miscEquips[index].netID != 0)
{
player.TPlayer.miscEquips[index].stack = this.inventory[i].Stack;
player.TPlayer.miscEquips[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots
+ NetItem.MiscDyeSlots)
{
//93-98
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots);
player.TPlayer.miscDyes[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.miscDyes[index].netID != 0)
{
player.TPlayer.miscDyes[index].stack = this.inventory[i].Stack;
player.TPlayer.miscDyes[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots +
NetItem.MiscDyeSlots + NetItem.PiggySlots)
{
//98-138
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots + NetItem.MiscDyeSlots);
player.TPlayer.bank.item[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.bank.item[index].netID != 0)
{
player.TPlayer.bank.item[index].stack = this.inventory[i].Stack;
player.TPlayer.bank.item[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else if (i <
NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots +
NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots)
{
var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots
+ NetItem.MiscEquipSlots + NetItem.MiscDyeSlots + NetItem.PiggySlots);
player.TPlayer.bank2.item[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.bank2.item[index].netID != 0)
{
player.TPlayer.bank2.item[index].stack = this.inventory[i].Stack;
player.TPlayer.bank2.item[index].prefix = (byte)this.inventory[i].PrefixId;
}
}
else
{
player.TPlayer.trashItem.netDefaults(this.inventory[i].NetId);
if (player.TPlayer.trashItem.netID != 0)
{
player.TPlayer.trashItem.stack = this.inventory[i].Stack;
player.TPlayer.trashItem.prefix = (byte)this.inventory[i].PrefixId;
}
}
}
float slot = 0f;
for (int k = 0; k < NetItem.InventorySlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].inventory[k].name, player.Index, slot, (float)Main.player[player.Index].inventory[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.ArmorSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[k].name, player.Index, slot, (float)Main.player[player.Index].armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.DyeSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[k].name, player.Index, slot, (float)Main.player[player.Index].dye[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.MiscEquipSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].miscEquips[k].name, player.Index, slot, (float)Main.player[player.Index].miscEquips[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.MiscDyeSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].miscDyes[k].name, player.Index, slot, (float)Main.player[player.Index].miscDyes[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.PiggySlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].bank.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank.item[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.SafeSlots; k++)
{
NetMessage.SendData(5, -1, -1, Main.player[player.Index].bank2.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank2.item[k].prefix);
slot++;
}
NetMessage.SendData(5, -1, -1, Main.player[player.Index].trashItem.name, player.Index, slot, (float)Main.player[player.Index].trashItem.prefix);
NetMessage.SendData(4, -1, -1, player.Name, player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(42, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(16, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
slot = 0f;
for (int k = 0; k < NetItem.InventorySlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].inventory[k].name, player.Index, slot, (float)Main.player[player.Index].inventory[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.ArmorSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[k].name, player.Index, slot, (float)Main.player[player.Index].armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.DyeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[k].name, player.Index, slot, (float)Main.player[player.Index].dye[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.MiscEquipSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].miscEquips[k].name, player.Index, slot, (float)Main.player[player.Index].miscEquips[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.MiscDyeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].miscDyes[k].name, player.Index, slot, (float)Main.player[player.Index].miscDyes[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.PiggySlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].bank.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank.item[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.SafeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].bank2.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank2.item[k].prefix);
slot++;
}
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].trashItem.name, player.Index, slot, (float)Main.player[player.Index].trashItem.prefix);
NetMessage.SendData(4, player.Index, -1, player.Name, player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(42, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(16, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
for (int k = 0; k < 22; k++)
{
player.TPlayer.buffType[k] = 0;
}
NetMessage.SendData(50, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(50, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
NetMessage.SendData(76, -1, -1, "", player.Index);
NetMessage.SendData(39, player.Index, -1, "", 400);
}
}
} }

160
TShockAPI/TSServerPlayer.cs Normal file
View file

@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using Terraria;
using TShockAPI;
using TShockAPI.DB;
public class TSServerPlayer : TSPlayer
{
public static string AccountName = "ServerConsole";
public TSServerPlayer()
: base("Server")
{
Group = new SuperAdminGroup();
User = new User { Name = AccountName };
}
public override void SendErrorMessage(string msg)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg);
Console.ResetColor();
}
public override void SendInfoMessage(string msg)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(msg);
Console.ResetColor();
}
public override void SendSuccessMessage(string msg)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(msg);
Console.ResetColor();
}
public override void SendWarningMessage(string msg)
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine(msg);
Console.ResetColor();
}
public override void SendMessage(string msg, Color color)
{
SendMessage(msg, color.R, color.G, color.B);
}
public override void SendMessage(string msg, byte red, byte green, byte blue)
{
Console.WriteLine(msg);
}
public void SetFullMoon()
{
Main.dayTime = false;
Main.moonPhase = 0;
Main.time = 0.0;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetBloodMoon(bool bloodMoon)
{
if (bloodMoon)
{
Main.dayTime = false;
Main.bloodMoon = true;
Main.time = 0.0;
}
else
Main.bloodMoon = false;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetFrostMoon(bool snowMoon)
{
if (snowMoon)
{
Main.dayTime = false;
Main.snowMoon = true;
Main.time = 0.0;
}
else
Main.snowMoon = false;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetPumpkinMoon(bool pumpkinMoon)
{
if (pumpkinMoon)
{
Main.dayTime = false;
Main.pumpkinMoon = true;
Main.time = 0.0;
}
else
Main.pumpkinMoon = false;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetEclipse(bool eclipse)
{
if (eclipse)
{
Main.dayTime = Main.eclipse = true;
Main.time = 0.0;
}
else
Main.eclipse = false;
TSPlayer.All.SendData(PacketTypes.WorldInfo);
}
public void SetTime(bool dayTime, double time)
{
Main.dayTime = dayTime;
Main.time = time;
TSPlayer.All.SendData(PacketTypes.TimeSet, "", dayTime ? 1 : 0, (int)time, Main.sunModY, Main.moonModY);
}
public void SpawnNPC(int type, string name, int amount, int startTileX, int startTileY, int tileXRange = 100,
int tileYRange = 50)
{
for (int i = 0; i < amount; i++)
{
int spawnTileX;
int spawnTileY;
TShock.Utils.GetRandomClearTileWithInRange(startTileX, startTileY, tileXRange, tileYRange, out spawnTileX,
out spawnTileY);
int npcid = NPC.NewNPC(spawnTileX * 16, spawnTileY * 16, type, 0);
// This is for special slimes
Main.npc[npcid].SetDefaults(name);
}
}
public void StrikeNPC(int npcid, int damage, float knockBack, int hitDirection)
{
// Main.rand is thread static.
if (Main.rand == null)
Main.rand = new Random();
Main.npc[npcid].StrikeNPC(damage, knockBack, hitDirection);
NetMessage.SendData((int)PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
}
public void RevertTiles(Dictionary<Vector2, Tile> tiles)
{
// Update Main.Tile first so that when tile sqaure is sent it is correct
foreach (KeyValuePair<Vector2, Tile> entry in tiles)
{
Main.tile[(int)entry.Key.X, (int)entry.Key.Y] = entry.Value;
}
// Send all players updated tile sqaures
foreach (Vector2 coords in tiles.Keys)
{
All.SendTileSquare((int)coords.X, (int)coords.Y, 3);
}
}
}

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

@ -89,6 +89,7 @@
<Compile Include="Hooks\RegionHooks.cs" /> <Compile Include="Hooks\RegionHooks.cs" />
<Compile Include="ILog.cs" /> <Compile Include="ILog.cs" />
<Compile Include="NetItem.cs" /> <Compile Include="NetItem.cs" />
<Compile Include="PlayerData.cs" />
<Compile Include="SqlLog.cs" /> <Compile Include="SqlLog.cs" />
<Compile Include="TextLog.cs" /> <Compile Include="TextLog.cs" />
<Compile Include="PaginationTools.cs" /> <Compile Include="PaginationTools.cs" />
@ -137,6 +138,7 @@
<Compile Include="Rest\SecureRest.cs" /> <Compile Include="Rest\SecureRest.cs" />
<Compile Include="ServerSideCharacters\ServerSideConfig.cs" /> <Compile Include="ServerSideCharacters\ServerSideConfig.cs" />
<Compile Include="StatTracker.cs" /> <Compile Include="StatTracker.cs" />
<Compile Include="TSServerPlayer.cs" />
<Compile Include="Utils.cs" /> <Compile Include="Utils.cs" />
<Compile Include="TShock.cs" /> <Compile Include="TShock.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@ -193,7 +195,7 @@
</PropertyGroup> </PropertyGroup>
<ProjectExtensions> <ProjectExtensions>
<VisualStudio> <VisualStudio>
<UserProperties BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_StartDate="2011/6/17" BuildVersion_IncrementBeforeBuild="False" /> <UserProperties BuildVersion_IncrementBeforeBuild="False" BuildVersion_StartDate="2011/6/17" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_BuildAction="Both" BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" />
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

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;