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.
## 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
* 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
* 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

View file

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

View file

@ -96,7 +96,7 @@ namespace TShockAPI.DB
playerData.extraSlot = reader.Get<int>("extraSlot");
playerData.spawnX = reader.Get<int>("spawnX");
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.hairDye = (byte)reader.Get<int>("hairDye");
playerData.hairColor = TShock.Utils.DecodeColor(reader.Get<int?>("hairColor"));
@ -162,13 +162,13 @@ namespace TShockAPI.DB
if (!player.IsLoggedIn)
return false;
if ((player.tempGroup != null && player.tempGroup.HasPermission(Permissions.bypassssc)) || player.Group.HasPermission(Permissions.bypassssc))
{
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + player.User.Name); // Debug code
return true;
}
if (player.HasPermission(Permissions.bypassssc))
{
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + player.User.Name); // Debug code
return true;
}
if (!GetPlayerData(player, player.User.ID).exists)
{
try

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -21,66 +21,221 @@ using System.ComponentModel;
namespace TShockAPI.Hooks
{
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerPostLogin"/> event.
/// </summary>
public class PlayerPostLoginEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// Initializes a new instance of the PlayerPostLoginEventArgs class.
/// </summary>
/// <param name="ply">The player who fired the event.</param>
public PlayerPostLoginEventArgs(TSPlayer ply)
{
Player = ply;
}
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerPreLogin"/> event.
/// </summary>
public class PlayerPreLoginEventArgs : HandledEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// The player's login name.
/// </summary>
public string LoginName { get; set; }
/// <summary>
/// The player's raw password.
/// </summary>
public string Password { get; set; }
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerLogout"/> event.
/// </summary>
public class PlayerLogoutEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// Initializes a new instance of the PlayerLogoutEventArgs class.
/// </summary>
/// <param name="player">The player who fired the event.</param>
public PlayerLogoutEventArgs(TSPlayer player)
{
Player = player;
}
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerCommand"/> event.
/// </summary>
public class PlayerCommandEventArgs : HandledEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// The command's name that follows the <see cref="Commands.Specifier"/>.
/// </summary>
public string CommandName { get; set; }
/// <summary>
/// The command's full text.
/// </summary>
public string CommandText { get; set; }
/// <summary>
/// The command's parameters extracted from <see cref="CommandText"/>.
/// </summary>
public List<string> Parameters { get; set; }
/// <summary>
/// The full list of server commands.
/// </summary>
public IEnumerable<Command> CommandList { get; set; }
/// <summary>
/// The prefix used to send the command (either <see cref="Commands.Specifier"/> or <see cref="Commands.SilentSpecifier"/>).
/// </summary>
public string CommandPrefix { get; set; }
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerChat"/> event.
/// </summary>
public class PlayerChatEventArgs : HandledEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// The raw chat text as received by the server.
/// </summary>
public string RawText { get; set; }
/// <summary>
/// The <see cref="RawText"/> string after being formatted by TShock as specified in the config file.
/// </summary>
public string TShockFormattedText { get; set; }
}
/// <summary>
/// EventArgs used for the <see cref="PlayerHooks.PlayerPermission"/> event.
/// </summary>
public class PlayerPermissionEventArgs : HandledEventArgs
{
/// <summary>
/// The player who fired the event.
/// </summary>
public TSPlayer Player { get; set; }
/// <summary>
/// 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
{
/// <summary>
/// The delegate of the <see cref="PlayerPostLogin"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerPostLoginD(PlayerPostLoginEventArgs e);
/// <summary>
/// Fired by players after they've successfully logged in to a user account.
/// </summary>
public static event PlayerPostLoginD PlayerPostLogin;
/// <summary>
/// The delegate of the <see cref="PlayerPreLogin"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerPreLoginD(PlayerPreLoginEventArgs e);
/// <summary>
/// Fired by players when sending login credentials to the server.
/// </summary>
public static event PlayerPreLoginD PlayerPreLogin;
/// <summary>
/// The delegate of the <see cref="PlayerLogout"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerLogoutD(PlayerLogoutEventArgs e);
/// <summary>
/// Fired by players upon logging out from a user account.
/// </summary>
public static event PlayerLogoutD PlayerLogout;
/// <summary>
/// The delegate of the <see cref="PlayerCommand"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerCommandD(PlayerCommandEventArgs e);
/// <summary>
/// Fired by players when using a command.
/// </summary>
public static event PlayerCommandD PlayerCommand;
/// <summary>
/// The delegate of the <see cref="PlayerChat"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerChatD(PlayerChatEventArgs e);
/// <summary>
/// Fired by players when they send a chat message packet to the server
/// and before it is transmitted to the rest of the players.
/// </summary>
public static event PlayerChatD PlayerChat;
/// <summary>
/// The delegate of the <see cref="PlayerPermission"/> event.
/// </summary>
/// <param name="e">The EventArgs for this event.</param>
public delegate void PlayerPermissionD(PlayerPermissionEventArgs e);
/// <summary>
/// Fired by players every time a permission check involving them occurs.
/// </summary>
public static event PlayerPermissionD PlayerPermission;
/// <summary>
/// Fires the <see cref="PlayerPostLogin"/> event.
/// </summary>
/// <param name="ply">The player firing the event.</param>
public static void OnPlayerPostLogin(TSPlayer ply)
{
if (PlayerPostLogin == null)
@ -92,6 +247,16 @@ namespace TShockAPI.Hooks
PlayerPostLogin(args);
}
/// <summary>
/// Fires the <see cref="PlayerCommand"/> event.
/// </summary>
/// <param name="player">The player firing the event.</param>
/// <param name="cmdName">The command name.</param>
/// <param name="cmdText">The raw command text.</param>
/// <param name="args">The command args extracted from the command text.</param>
/// <param name="commands">The list of commands.</param>
/// <param name="cmdPrefix">The command specifier used.</param>
/// <returns>True if the event has been handled.</returns>
public static bool OnPlayerCommand(TSPlayer player, string cmdName, string cmdText, List<string> args, ref IEnumerable<Command> commands, string cmdPrefix)
{
if (PlayerCommand == null)
@ -111,6 +276,13 @@ namespace TShockAPI.Hooks
return playerCommandEventArgs.Handled;
}
/// <summary>
/// Fires the <see cref="PlayerPreLogin"/> event.
/// </summary>
/// <param name="ply">The player firing the event.</param>
/// <param name="name">The user name.</param>
/// <param name="pass">The password.</param>
/// <returns>True if the event has been handled.</returns>
public static bool OnPlayerPreLogin(TSPlayer ply, string name, string pass)
{
if (PlayerPreLogin == null)
@ -121,6 +293,10 @@ namespace TShockAPI.Hooks
return args.Handled;
}
/// <summary>
/// Fires the <see cref="PlayerLogout"/> event.
/// </summary>
/// <param name="ply">The player firing the event.</param>
public static void OnPlayerLogout(TSPlayer ply)
{
if (PlayerLogout == null)
@ -130,6 +306,12 @@ namespace TShockAPI.Hooks
PlayerLogout(args);
}
/// <summary>
/// Fires the <see cref="PlayerChat"/> event.
/// </summary>
/// <param name="ply">The player firing the event.</param>
/// <param name="rawtext">The raw chat text sent by the player.</param>
/// <param name="tshockText">The chat text after being formatted.</param>
public static void OnPlayerChat(TSPlayer ply, string rawtext, ref string tshockText)
{
if (PlayerChat == null)
@ -139,5 +321,20 @@ namespace TShockAPI.Hooks
PlayerChat(args);
tshockText = args.TShockFormattedText;
}
/// <summary>
/// Fires the <see cref="PlayerPermission"/> event.
/// </summary>
/// <param name="player">The player firing the event.</param>
/// <returns>True if the event has been handled.</returns>
public static bool OnPlayerPermission(TSPlayer player, 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.ID;
using TShockAPI.DB;
using TShockAPI.Hooks;
using TShockAPI.Net;
using Timer = System.Timers.Timer;
@ -430,11 +431,11 @@ namespace TShockAPI
}
try
{
if ((tempGroup != null && tempGroup.HasPermission(Permissions.bypassssc)) || Group.HasPermission(Permissions.bypassssc))
{
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + User.Name); // Debug Code
return true;
}
if (HasPermission(Permissions.bypassssc))
{
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + User.Name); // Debug Code
return true;
}
PlayerData.CopyCharacter(this);
TShock.CharacterDB.InsertPlayerData(this);
return true;
@ -875,22 +876,22 @@ namespace TShockAPI
}
}
/*
* Calling new StackTrace() is incredibly expensive, and must be disabled
* in release builds. Use a conditional call instead.
*/
LogStackFrame();
/*
* Calling new StackTrace() is incredibly expensive, and must be disabled
* in release builds. Use a conditional call instead.
*/
LogStackFrame();
}
[Conditional("DEBUG")]
private void LogStackFrame()
{
var trace = new StackTrace();
StackFrame frame = null;
frame = trace.GetFrame(1);
if (frame != null && frame.GetMethod().DeclaringType != null)
TShock.Log.Debug(frame.GetMethod().DeclaringType.Name + " called Disable().");
}
[Conditional("DEBUG")]
private void LogStackFrame()
{
var trace = new StackTrace();
StackFrame frame = null;
frame = trace.GetFrame(1);
if (frame != null && frame.GetMethod().DeclaringType != null)
TShock.Log.Debug(frame.GetMethod().DeclaringType.Name + " called Disable().");
}
public virtual void Whoopie(object time)
{
@ -954,6 +955,22 @@ namespace TShockAPI
AwaitingResponse.Add(name, callback);
}
/// <summary>
/// Checks to see if a player or its associated group/temporary group has a specified permission.
/// </summary>
/// <param name="permission">The permission to check.</param>
/// <returns>True if the player has that permission.</returns>
public bool HasPermission(string permission)
{
if (PlayerHooks.OnPlayerPermission(this, permission))
return true;
if (tempGroup != null)
return tempGroup.HasPermission(permission);
else
return Group.HasPermission(permission);
}
}
public class TSRestPlayer : TSPlayer
@ -1001,568 +1018,4 @@ namespace TShockAPI
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";
foreach (Item item in player.TPlayer.inventory)
{
if (!player.Group.HasPermission(Permissions.ignorestackhackdetection) && (item.stack > item.maxStack || item.stack < 0) &&
if (!player.HasPermission(Permissions.ignorestackhackdetection) && (item.stack > item.maxStack || item.stack < 0) &&
item.type != 0)
{
check = "Remove item " + item.name + " (" + item.stack + ") exceeds max stack of " + item.maxStack;
@ -1334,7 +1334,7 @@ namespace TShockAPI
}
else
{
if (!tsplr.Group.HasPermission(Permissions.canchat))
if (!tsplr.HasPermission(Permissions.canchat))
{
args.Handled = true;
}
@ -1652,7 +1652,7 @@ namespace TShockAPI
/// <returns>bool - True if the player should not be able to modify a tile.</returns>
public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY, short tileType, GetDataHandlers.EditAction actionType)
{
if (!player.Group.HasPermission(Permissions.canbuild))
if (!player.HasPermission(Permissions.canbuild))
{
if (TShock.Config.AllowIce && actionType != GetDataHandlers.EditAction.PlaceTile)
{
@ -1687,7 +1687,7 @@ namespace TShockAPI
return true;
}
if (!player.Group.HasPermission(Permissions.editregion) && !Regions.CanBuild(tileX, tileY, player) &&
if (!player.HasPermission(Permissions.editregion) && !Regions.CanBuild(tileX, tileY, player) &&
Regions.InArea(tileX, tileY))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000)
@ -1700,7 +1700,7 @@ namespace TShockAPI
if (Config.DisableBuild)
{
if (!player.Group.HasPermission(Permissions.antibuild))
if (!player.HasPermission(Permissions.antibuild))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000)
{
@ -1713,7 +1713,7 @@ namespace TShockAPI
if (Config.SpawnProtection)
{
if (!player.Group.HasPermission(Permissions.editspawn))
if (!player.HasPermission(Permissions.editspawn))
{
if (CheckSpawn(tileX, tileY))
{
@ -1737,8 +1737,8 @@ namespace TShockAPI
/// <returns>bool - True if the player should not be able to modify the tile.</returns>
public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY, bool paint = false)
{
if ((!paint && !player.Group.HasPermission(Permissions.canbuild)) ||
(paint && !player.Group.HasPermission(Permissions.canpaint)))
if ((!paint && !player.HasPermission(Permissions.canbuild)) ||
(paint && !player.HasPermission(Permissions.canpaint)))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000)
{
@ -1755,7 +1755,7 @@ namespace TShockAPI
return true;
}
if (!player.Group.HasPermission(Permissions.editregion) && !Regions.CanBuild(tileX, tileY, player) &&
if (!player.HasPermission(Permissions.editregion) && !Regions.CanBuild(tileX, tileY, player) &&
Regions.InArea(tileX, tileY))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000)
@ -1768,7 +1768,7 @@ namespace TShockAPI
if (Config.DisableBuild)
{
if (!player.Group.HasPermission(Permissions.antibuild))
if (!player.HasPermission(Permissions.antibuild))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000)
{
@ -1781,7 +1781,7 @@ namespace TShockAPI
if (Config.SpawnProtection)
{
if (!player.Group.HasPermission(Permissions.editspawn))
if (!player.HasPermission(Permissions.editspawn))
{
if (CheckSpawn(tileX, tileY))
{

View file

@ -89,6 +89,7 @@
<Compile Include="Hooks\RegionHooks.cs" />
<Compile Include="ILog.cs" />
<Compile Include="NetItem.cs" />
<Compile Include="PlayerData.cs" />
<Compile Include="SqlLog.cs" />
<Compile Include="TextLog.cs" />
<Compile Include="PaginationTools.cs" />
@ -137,6 +138,7 @@
<Compile Include="Rest\SecureRest.cs" />
<Compile Include="ServerSideCharacters\ServerSideConfig.cs" />
<Compile Include="StatTracker.cs" />
<Compile Include="TSServerPlayer.cs" />
<Compile Include="Utils.cs" />
<Compile Include="TShock.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@ -193,7 +195,7 @@
</PropertyGroup>
<ProjectExtensions>
<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>
</ProjectExtensions>
<!-- 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);
foreach (TSPlayer player in TShock.Players)
{
if (player != null && player.Active && player.Group.HasPermission(Permissions.maintenance))
if (player != null && player.Active && player.HasPermission(Permissions.maintenance))
{
NotifyAdministrator(player, changes);
}

View file

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