diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs
index 5aed7b6c..e1da8b94 100644
--- a/TShockAPI/ConfigFile.cs
+++ b/TShockAPI/ConfigFile.cs
@@ -177,6 +177,12 @@ namespace TShockAPI
[Description("Disables hardmode, can't never be activated. Overrides /starthardmode")]
public bool DisableHardmode = false;
+ [Description("Disables Dungeon Guardian from being spawned by player packets, this will instead force a respawn")]
+ public bool DisableDungeonGuardian = false;
+
+ [Description("Enable Server Side Inventory checks, EXPERIMENTAL")]
+ public bool ServerSideInventory = false;
+
public static ConfigFile Read(string path)
{
if (!File.Exists(path))
diff --git a/TShockAPI/DB/InventoryManager.cs b/TShockAPI/DB/InventoryManager.cs
new file mode 100644
index 00000000..28fc90e3
--- /dev/null
+++ b/TShockAPI/DB/InventoryManager.cs
@@ -0,0 +1,100 @@
+/*
+TShock, a server mod for Terraria
+Copyright (C) 2011 The TShock Team
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+using System;
+using System.Data;
+
+using MySql.Data.MySqlClient;
+using Terraria;
+
+namespace TShockAPI.DB
+{
+ public class InventoryManager
+ {
+ public IDbConnection database;
+
+ public InventoryManager(IDbConnection db)
+ {
+ database = db;
+
+ var table = new SqlTable("Inventory",
+ new SqlColumn("AccountName", MySqlDbType.VarChar, 32) { Primary = true },
+ new SqlColumn("CharacterName", MySqlDbType.VarChar, 50),
+ new SqlColumn("MaxHealth", MySqlDbType.Int32),
+ new SqlColumn("MaxMana", MySqlDbType.Int32),
+ new SqlColumn("Inventory", MySqlDbType.Text)
+ );
+ var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator());
+ creator.EnsureExists(table);
+ }
+
+ public PlayerData GetPlayerData(TSPlayer player)
+ {
+ PlayerData playerData = new PlayerData(player);
+
+ try
+ {
+ using (var reader = database.QueryReader("SELECT * FROM Inventory WHERE AccountName=@0 AND CharacterName=@1", player.UserAccountName, player.Name))
+ {
+ if (reader.Read())
+ {
+ playerData.exists = true;
+ playerData.maxHealth = reader.Get("MaxHealth");
+ playerData.maxMana = reader.Get("MaxMana");
+ playerData.inventory = NetItem.Parse(reader.Get("Inventory"));
+ return playerData;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex.ToString());
+ }
+
+ return playerData;
+ }
+
+ public void InsertPlayerData(TSPlayer player)
+ {
+ PlayerData playerData = player.PlayerData;
+
+ if (!GetPlayerData(player).exists)
+ {
+ try
+ {
+ database.Query("INSERT INTO Inventory (AccountName, CharacterName, MaxHealth, MaxMana, Inventory) VALUES (@0, @1, @2, @3, @4);", playerData.accountName, playerData.characterName, playerData.maxHealth, playerData.maxMana, NetItem.ToString(playerData.inventory));
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex.ToString());
+ }
+ }
+ else
+ {
+ try
+ {
+ database.Query("UPDATE Inventory SET MaxHealth = @0, MaxMana = @1, Inventory = @3 WHERE AccountName = @4 AND CharacterName = @5;", playerData.maxHealth, playerData.maxMana, NetItem.ToString(playerData.inventory), playerData.accountName, playerData.characterName);
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex.ToString());
+ }
+ }
+ }
+ }
+}
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 5cedfaab..73c2e849 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -90,6 +90,7 @@ namespace TShockAPI
{PacketTypes.PlayerDamage, HandlePlayerDamage},
{PacketTypes.NpcStrike, HandleNpcStrike},
{PacketTypes.NpcSpecial, HandleSpecial},
+ {PacketTypes.PlayerAnimation, HandlePlayerAnimation},
};
}
@@ -254,7 +255,7 @@ namespace TShockAPI
return true;
}
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
@@ -470,7 +471,7 @@ namespace TShockAPI
}
}
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
@@ -520,6 +521,12 @@ namespace TShockAPI
}
args.TPlayer.hostile = pvp;
+
+ if (pvp == true && TShock.Config.AlwaysPvP)
+ args.Player.IgnoreActionsForPvP = false;
+ else
+ args.Player.IgnoreActionsForPvP = true;
+
NetMessage.SendData((int)PacketTypes.TogglePvp, -1, -1, "", args.Player.Index);
return true;
@@ -551,9 +558,12 @@ namespace TShockAPI
if (!pos.Equals(args.Player.LastNetPosition))
{
float distance = Vector2.Distance(new Vector2((pos.X / 16f), (pos.Y / 16f)), new Vector2(Main.spawnTileX, Main.spawnTileY));
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile && distance > 6f)
+ if (TShock.CheckIgnores(args.Player) && distance > 6f)
{
- args.Player.SendMessage("PvP is forced! Enable PvP else you can't do anything!", Color.Red);
+ if (TShock.Config.AlwaysPvP)
+ {
+ args.Player.SendMessage("PvP is forced! Enable PvP else you can't move or do anything!", Color.Red);
+ }
args.Player.Spawn();
return true;
}
@@ -599,7 +609,7 @@ namespace TShockAPI
return true;
}
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendData(PacketTypes.ProjectileNew, "", index);
return true;
@@ -640,7 +650,7 @@ namespace TShockAPI
return true;
}
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendData(PacketTypes.ProjectileNew, "", index);
return true;
@@ -696,7 +706,7 @@ namespace TShockAPI
if (tileX < 0 || tileX >= Main.maxTilesX || tileY < 0 || tileY >= Main.maxTilesY)
return false;
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
@@ -751,7 +761,7 @@ namespace TShockAPI
if (tileX < 0 || tileX >= Main.maxTilesX || tileY < 0 || tileY >= Main.maxTilesY)
return false;
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
@@ -808,7 +818,7 @@ namespace TShockAPI
var x = args.Data.ReadInt32();
var y = args.Data.ReadInt32();
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
return true;
}
@@ -833,7 +843,7 @@ namespace TShockAPI
return false;
}
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendData(PacketTypes.ChestItem, "", id, slot);
return true;
@@ -907,7 +917,7 @@ namespace TShockAPI
var type = args.Data.ReadInt8();
var time = args.Data.ReadInt16();
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendData(PacketTypes.PlayerBuff, "", id);
return true;
@@ -964,7 +974,7 @@ namespace TShockAPI
return true;
}
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendData(PacketTypes.ItemDrop, "", id);
return true;
@@ -1009,7 +1019,7 @@ namespace TShockAPI
return true;
}
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendData(PacketTypes.PlayerHp, "", id);
args.Player.SendData(PacketTypes.PlayerUpdate, "", id);
@@ -1050,7 +1060,7 @@ namespace TShockAPI
return true;
}
- if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile)
+ if (TShock.CheckIgnores(args.Player))
{
args.Player.SendData(PacketTypes.NpcUpdate, "", id);
return true;
@@ -1082,6 +1092,30 @@ namespace TShockAPI
var id = args.Data.ReadInt8();
var type = args.Data.ReadInt8();
+ if (type == 1 && TShock.Config.DisableDungeonGuardian)
+ {
+ args.Player.SendMessage("The Dungeon Guardian returned you to your spawn point", Color.Purple);
+ args.Player.Spawn();
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool HandlePlayerAnimation(GetDataHandlerArgs args)
+ {
+ if (TShock.CheckIgnores(args.Player))
+ {
+ args.Player.SendData(PacketTypes.PlayerAnimation, "", args.Player.Index);
+ return true;
+ }
+
+ if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000)
+ {
+ args.Player.SendData(PacketTypes.PlayerAnimation, "", args.Player.Index);
+ return true;
+ }
+
return false;
}
}
diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs
index c2994944..c5ec7a28 100644
--- a/TShockAPI/TSPlayer.cs
+++ b/TShockAPI/TSPlayer.cs
@@ -64,6 +64,9 @@ namespace TShockAPI
public string Country = "??";
public int Difficulty;
private string CacheIP;
+ public bool IgnoreActionsForPvP = false;
+ public bool IgnoreActionsForInventory = false;
+ public PlayerData PlayerData;
public bool RealPlayer
{
@@ -429,4 +432,52 @@ namespace TShockAPI
}
}
}
+
+ public class PlayerData
+ {
+ public NetItem[] inventory = new NetItem[NetItem.maxNetInventory];
+ public int maxHealth = 100;
+ public int maxMana = 100;
+ public string accountName;
+ public string characterName;
+ public bool exists = false;
+
+ public PlayerData(TSPlayer player)
+ {
+ this.accountName = player.UserAccountName;
+ this.characterName = player.Name;
+ this.inventory[0].netID = -15;
+ this.inventory[0].stack = 1;
+ if(player.TPlayer.inventory[0].netID == -15)
+ this.inventory[0].prefix = player.TPlayer.inventory[0].prefix;
+ this.inventory[1].netID = -13;
+ this.inventory[1].stack = 1;
+ if (player.TPlayer.inventory[1].netID == -13)
+ this.inventory[1].prefix = player.TPlayer.inventory[1].prefix;
+ this.inventory[2].netID = -16;
+ this.inventory[2].stack = 1;
+ if (player.TPlayer.inventory[2].netID == -16)
+ this.inventory[2].prefix = player.TPlayer.inventory[2].prefix;
+ }
+ }
+
+ public class NetItem
+ {
+ public static int maxNetInventory = 59;
+ public int netID = 0;
+ public int stack = 0;
+ public int prefix = 0;
+
+ public static string ToString(NetItem[] inventory)
+ {
+ string inventoryString = "";
+ return inventoryString;
+ }
+
+ public static NetItem[] Parse(string data)
+ {
+ NetItem[] inventory = new NetItem[NetItem.maxNetInventory];
+ return inventory;
+ }
+ }
}
\ No newline at end of file
diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs
index ea14fba6..4af85358 100644
--- a/TShockAPI/TShock.cs
+++ b/TShockAPI/TShock.cs
@@ -62,6 +62,7 @@ namespace TShockAPI
public static UserManager Users;
public static ItemManager Itembans;
public static RemeberedPosManager RememberedPos;
+ public static InventoryManager Inventory;
public static ConfigFile Config { get; set; }
public static IDbConnection DB;
public static bool OverridePort;
@@ -177,6 +178,7 @@ namespace TShockAPI
Regions = new RegionManager(DB);
Itembans = new ItemManager(DB);
RememberedPos = new RemeberedPosManager(DB);
+ Inventory = new InventoryManager(DB);
RestApi = new SecureRest(Netplay.serverListenIP, 8080);
RestApi.Verify += RestApi_Verify;
RestApi.Port = Config.RestApiPort;
@@ -721,10 +723,12 @@ namespace TShockAPI
TShock.Utils.HandleCheater(player, "Health/Mana cheat detected. Please use a different character.");
}
+
NetMessage.syncPlayers();
- if (Config.AlwaysPvP)
+ if (Config.AlwaysPvP && !player.TPlayer.hostile)
{
+ player.IgnoreActionsForPvP = true;
player.SendMessage("PvP is forced! Enable PvP else you can't move or do anything!", Color.Red);
}
if (player.Group.HasPermission(Permissions.causeevents) && Config.InfiniteInvasion)
@@ -999,6 +1003,22 @@ namespace TShockAPI
(player.TPlayer.statLife > 400);
}
+ public static bool CheckInventory(TSPlayer player)
+ {
+
+ return false;
+ }
+
+ public static bool CheckIgnores(TSPlayer player)
+ {
+ bool check = false;
+ if (player.IgnoreActionsForPvP)
+ check = true;
+ if (player.IgnoreActionsForInventory)
+ check = true;
+ return check;
+ }
+
public static bool CheckPlayerCollision(int x, int y)
{
if (x + 1 <= Main.maxTilesX && y + 3 <= Main.maxTilesY
diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj
index 0fc0d777..3d024668 100644
--- a/TShockAPI/TShockAPI.csproj
+++ b/TShockAPI/TShockAPI.csproj
@@ -84,6 +84,7 @@
+
@@ -180,7 +181,7 @@
-
+