Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions TShockAPI/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,24 @@ public static void InitCommands()
{
HelpText = GetString("Shows the server's rules.")
});
add(new Command(ShowDeath, "death")
{
HelpText = GetString("Shows your number of deaths."),
AllowServer = false
});
add(new Command(ShowPVPDeath, "pvpdeath")
{
HelpText = GetString("Shows your number of PVP deaths."),
AllowServer = false
});
add(new Command(ShowAllDeath, "alldeath")
{
HelpText = GetString("Shows the number of deaths for all online players."),
});
add(new Command(ShowAllPVPDeath, "allpvpdeath")
{
HelpText = GetString("Shows the number of PVP deaths for all online players."),
});

TShockCommands = new ReadOnlyCollection<Command>(tshockCommands);
}
Expand Down Expand Up @@ -5815,6 +5833,49 @@ private static void SyncLocalArea(CommandArgs args)
return;
}

private static void ShowDeath(CommandArgs args)
{
args.Player.SendErrorMessage(GetString($"*You were slain {args.Player.DeathsPVE} times."));
}

private static void ShowPVPDeath(CommandArgs args)
{
args.Player.SendErrorMessage(GetString($"*You were slain by other players {args.Player.DeathsPVP} times."));
}

private static void ShowAllDeath(CommandArgs args)
{
if (TShock.Utils.GetActivePlayerCount() == 0)
{
args.Player.SendErrorMessage(GetString("There are currently no players online."));
return;
}

var deathsRank = TShock.Players
.Where(p => p is { Active: true })
.OrderByDescending(x => x.DeathsPVE)
.Select(x => GetString($"*{x.Name} was slain {x.DeathsPVE} times."));

args.Player.SendErrorMessage(string.Join('\n',deathsRank));
}

private static void ShowAllPVPDeath(CommandArgs args)
{
if (TShock.Utils.GetActivePlayerCount() == 0)
{
args.Player.SendErrorMessage(GetString("There are currently no players online."));
return;
}

var deathsRank = TShock.Players
.Where(p => p is { Active: true })
.OrderByDescending(x => x.DeathsPVP)
.Select(x => GetString($"*{x.Name} was slain by other players {x.DeathsPVP} times."));

args.Player.SendErrorMessage(string.Join('\n',deathsRank));
}


#endregion General Commands

#region Game Commands
Expand Down
28 changes: 19 additions & 9 deletions TShockAPI/DB/CharacterManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ public CharacterManager(IDbConnection db)
new SqlColumn("usedGummyWorm", MySqlDbType.Int32),
new SqlColumn("usedAmbrosia", MySqlDbType.Int32),
new SqlColumn("unlockedSuperCart", MySqlDbType.Int32),
new SqlColumn("enabledSuperCart", MySqlDbType.Int32)
new SqlColumn("enabledSuperCart", MySqlDbType.Int32),
new SqlColumn("deathsPVE", MySqlDbType.Int32),
new SqlColumn("deathsPVP", MySqlDbType.Int32)
);

SqlTableCreator creator = new(db, db.GetSqlQueryBuilder());
Expand Down Expand Up @@ -132,6 +134,8 @@ public PlayerData GetPlayerData(TSPlayer player, int acctid)
playerData.usedAmbrosia = reader.Get<int>("usedAmbrosia");
playerData.unlockedSuperCart = reader.Get<int>("unlockedSuperCart");
playerData.enabledSuperCart = reader.Get<int>("enabledSuperCart");
playerData.deathsPVE = reader.Get<int>("deathsPVE");
playerData.deathsPVP = reader.Get<int>("deathsPVP");
return playerData;
}
}
Expand Down Expand Up @@ -200,8 +204,8 @@ public bool InsertPlayerData(TSPlayer player, bool fromCommand = false)
try
{
database.Query(
"INSERT INTO tsCharacter (Account, Health, MaxHealth, Mana, MaxMana, Inventory, extraSlot, spawnX, spawnY, skinVariant, hair, hairDye, hairColor, pantsColor, shirtColor, underShirtColor, shoeColor, hideVisuals, skinColor, eyeColor, questsCompleted, usingBiomeTorches, happyFunTorchTime, unlockedBiomeTorches, currentLoadoutIndex,ateArtisanBread, usedAegisCrystal, usedAegisFruit, usedArcaneCrystal, usedGalaxyPearl, usedGummyWorm, usedAmbrosia, unlockedSuperCart, enabledSuperCart) VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22, @23, @24, @25, @26, @27, @28, @29, @30, @31, @32, @33);",
player.Account.ID, playerData.health, playerData.maxHealth, playerData.mana, playerData.maxMana, string.Join("~", playerData.inventory), playerData.extraSlot, player.TPlayer.SpawnX, player.TPlayer.SpawnY, player.TPlayer.skinVariant, player.TPlayer.hair, player.TPlayer.hairDye, TShock.Utils.EncodeColor(player.TPlayer.hairColor), TShock.Utils.EncodeColor(player.TPlayer.pantsColor),TShock.Utils.EncodeColor(player.TPlayer.shirtColor), TShock.Utils.EncodeColor(player.TPlayer.underShirtColor), TShock.Utils.EncodeColor(player.TPlayer.shoeColor), TShock.Utils.EncodeBoolArray(player.TPlayer.hideVisibleAccessory), TShock.Utils.EncodeColor(player.TPlayer.skinColor),TShock.Utils.EncodeColor(player.TPlayer.eyeColor), player.TPlayer.anglerQuestsFinished, player.TPlayer.UsingBiomeTorches ? 1 : 0, player.TPlayer.happyFunTorchTime ? 1 : 0, player.TPlayer.unlockedBiomeTorches ? 1 : 0, player.TPlayer.CurrentLoadoutIndex, player.TPlayer.ateArtisanBread ? 1 : 0, player.TPlayer.usedAegisCrystal ? 1 : 0, player.TPlayer.usedAegisFruit ? 1 : 0, player.TPlayer.usedArcaneCrystal ? 1 : 0, player.TPlayer.usedGalaxyPearl ? 1 : 0, player.TPlayer.usedGummyWorm ? 1 : 0, player.TPlayer.usedAmbrosia ? 1 : 0, player.TPlayer.unlockedSuperCart ? 1 : 0, player.TPlayer.enabledSuperCart ? 1 : 0);
"INSERT INTO tsCharacter (Account, Health, MaxHealth, Mana, MaxMana, Inventory, extraSlot, spawnX, spawnY, skinVariant, hair, hairDye, hairColor, pantsColor, shirtColor, underShirtColor, shoeColor, hideVisuals, skinColor, eyeColor, questsCompleted, usingBiomeTorches, happyFunTorchTime, unlockedBiomeTorches, currentLoadoutIndex,ateArtisanBread, usedAegisCrystal, usedAegisFruit, usedArcaneCrystal, usedGalaxyPearl, usedGummyWorm, usedAmbrosia, unlockedSuperCart, enabledSuperCart, deathsPVE, deathsPVP) VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22, @23, @24, @25, @26, @27, @28, @29, @30, @31, @32, @33, @34, @35);",
player.Account.ID, playerData.health, playerData.maxHealth, playerData.mana, playerData.maxMana, string.Join("~", playerData.inventory), playerData.extraSlot, player.TPlayer.SpawnX, player.TPlayer.SpawnY, player.TPlayer.skinVariant, player.TPlayer.hair, player.TPlayer.hairDye, TShock.Utils.EncodeColor(player.TPlayer.hairColor), TShock.Utils.EncodeColor(player.TPlayer.pantsColor),TShock.Utils.EncodeColor(player.TPlayer.shirtColor), TShock.Utils.EncodeColor(player.TPlayer.underShirtColor), TShock.Utils.EncodeColor(player.TPlayer.shoeColor), TShock.Utils.EncodeBoolArray(player.TPlayer.hideVisibleAccessory), TShock.Utils.EncodeColor(player.TPlayer.skinColor),TShock.Utils.EncodeColor(player.TPlayer.eyeColor), player.TPlayer.anglerQuestsFinished, player.TPlayer.UsingBiomeTorches ? 1 : 0, player.TPlayer.happyFunTorchTime ? 1 : 0, player.TPlayer.unlockedBiomeTorches ? 1 : 0, player.TPlayer.CurrentLoadoutIndex, player.TPlayer.ateArtisanBread ? 1 : 0, player.TPlayer.usedAegisCrystal ? 1 : 0, player.TPlayer.usedAegisFruit ? 1 : 0, player.TPlayer.usedArcaneCrystal ? 1 : 0, player.TPlayer.usedGalaxyPearl ? 1 : 0, player.TPlayer.usedGummyWorm ? 1 : 0, player.TPlayer.usedAmbrosia ? 1 : 0, player.TPlayer.unlockedSuperCart ? 1 : 0, player.TPlayer.enabledSuperCart ? 1 : 0, player.sscDeathsPVE, player.sscDeathsPVP);
return true;
}
catch (Exception ex)
Expand All @@ -214,8 +218,8 @@ public bool InsertPlayerData(TSPlayer player, bool fromCommand = false)
try
{
database.Query(
"UPDATE tsCharacter SET Health = @0, MaxHealth = @1, Mana = @2, MaxMana = @3, Inventory = @4, spawnX = @6, spawnY = @7, hair = @8, hairDye = @9, hairColor = @10, pantsColor = @11, shirtColor = @12, underShirtColor = @13, shoeColor = @14, hideVisuals = @15, skinColor = @16, eyeColor = @17, questsCompleted = @18, skinVariant = @19, extraSlot = @20, usingBiomeTorches = @21, happyFunTorchTime = @22, unlockedBiomeTorches = @23, currentLoadoutIndex = @24, ateArtisanBread = @25, usedAegisCrystal = @26, usedAegisFruit = @27, usedArcaneCrystal = @28, usedGalaxyPearl = @29, usedGummyWorm = @30, usedAmbrosia = @31, unlockedSuperCart = @32, enabledSuperCart = @33 WHERE Account = @5;",
playerData.health, playerData.maxHealth, playerData.mana, playerData.maxMana, string.Join("~", playerData.inventory), player.Account.ID, player.TPlayer.SpawnX, player.TPlayer.SpawnY, player.TPlayer.hair, player.TPlayer.hairDye, TShock.Utils.EncodeColor(player.TPlayer.hairColor), TShock.Utils.EncodeColor(player.TPlayer.pantsColor), TShock.Utils.EncodeColor(player.TPlayer.shirtColor), TShock.Utils.EncodeColor(player.TPlayer.underShirtColor), TShock.Utils.EncodeColor(player.TPlayer.shoeColor), TShock.Utils.EncodeBoolArray(player.TPlayer.hideVisibleAccessory), TShock.Utils.EncodeColor(player.TPlayer.skinColor), TShock.Utils.EncodeColor(player.TPlayer.eyeColor), player.TPlayer.anglerQuestsFinished, player.TPlayer.skinVariant, player.TPlayer.extraAccessory ? 1 : 0, player.TPlayer.UsingBiomeTorches ? 1 : 0, player.TPlayer.happyFunTorchTime ? 1 : 0, player.TPlayer.unlockedBiomeTorches ? 1 : 0, player.TPlayer.CurrentLoadoutIndex, player.TPlayer.ateArtisanBread ? 1 : 0, player.TPlayer.usedAegisCrystal ? 1 : 0, player.TPlayer.usedAegisFruit ? 1 : 0, player.TPlayer.usedArcaneCrystal ? 1 : 0, player.TPlayer.usedGalaxyPearl ? 1 : 0, player.TPlayer.usedGummyWorm ? 1 : 0, player.TPlayer.usedAmbrosia ? 1 : 0, player.TPlayer.unlockedSuperCart ? 1 : 0, player.TPlayer.enabledSuperCart ? 1 : 0);
"UPDATE tsCharacter SET Health = @0, MaxHealth = @1, Mana = @2, MaxMana = @3, Inventory = @4, spawnX = @6, spawnY = @7, hair = @8, hairDye = @9, hairColor = @10, pantsColor = @11, shirtColor = @12, underShirtColor = @13, shoeColor = @14, hideVisuals = @15, skinColor = @16, eyeColor = @17, questsCompleted = @18, skinVariant = @19, extraSlot = @20, usingBiomeTorches = @21, happyFunTorchTime = @22, unlockedBiomeTorches = @23, currentLoadoutIndex = @24, ateArtisanBread = @25, usedAegisCrystal = @26, usedAegisFruit = @27, usedArcaneCrystal = @28, usedGalaxyPearl = @29, usedGummyWorm = @30, usedAmbrosia = @31, unlockedSuperCart = @32, enabledSuperCart = @33, deathsPVE = @34, deathsPVP = @35 WHERE Account = @5;",
playerData.health, playerData.maxHealth, playerData.mana, playerData.maxMana, string.Join("~", playerData.inventory), player.Account.ID, player.TPlayer.SpawnX, player.TPlayer.SpawnY, player.TPlayer.hair, player.TPlayer.hairDye, TShock.Utils.EncodeColor(player.TPlayer.hairColor), TShock.Utils.EncodeColor(player.TPlayer.pantsColor), TShock.Utils.EncodeColor(player.TPlayer.shirtColor), TShock.Utils.EncodeColor(player.TPlayer.underShirtColor), TShock.Utils.EncodeColor(player.TPlayer.shoeColor), TShock.Utils.EncodeBoolArray(player.TPlayer.hideVisibleAccessory), TShock.Utils.EncodeColor(player.TPlayer.skinColor), TShock.Utils.EncodeColor(player.TPlayer.eyeColor), player.TPlayer.anglerQuestsFinished, player.TPlayer.skinVariant, player.TPlayer.extraAccessory ? 1 : 0, player.TPlayer.UsingBiomeTorches ? 1 : 0, player.TPlayer.happyFunTorchTime ? 1 : 0, player.TPlayer.unlockedBiomeTorches ? 1 : 0, player.TPlayer.CurrentLoadoutIndex, player.TPlayer.ateArtisanBread ? 1 : 0, player.TPlayer.usedAegisCrystal ? 1 : 0, player.TPlayer.usedAegisFruit ? 1 : 0, player.TPlayer.usedArcaneCrystal ? 1 : 0, player.TPlayer.usedGalaxyPearl ? 1 : 0, player.TPlayer.usedGummyWorm ? 1 : 0, player.TPlayer.usedAmbrosia ? 1 : 0, player.TPlayer.unlockedSuperCart ? 1 : 0, player.TPlayer.enabledSuperCart ? 1 : 0, player.sscDeathsPVE, player.sscDeathsPVP);
return true;
}
catch (Exception ex)
Expand Down Expand Up @@ -270,7 +274,7 @@ public bool InsertSpecificPlayerData(TSPlayer player, PlayerData data)
try
{
database.Query(
"INSERT INTO tsCharacter (Account, Health, MaxHealth, Mana, MaxMana, Inventory, extraSlot, spawnX, spawnY, skinVariant, hair, hairDye, hairColor, pantsColor, shirtColor, underShirtColor, shoeColor, hideVisuals, skinColor, eyeColor, questsCompleted, usingBiomeTorches, happyFunTorchTime, unlockedBiomeTorches, currentLoadoutIndex, ateArtisanBread, usedAegisCrystal, usedAegisFruit, usedArcaneCrystal, usedGalaxyPearl, usedGummyWorm, usedAmbrosia, unlockedSuperCart, enabledSuperCart) VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22, @23, @24, @25, @26, @27, @28, @29, @30, @31, @32, @33);",
"INSERT INTO tsCharacter (Account, Health, MaxHealth, Mana, MaxMana, Inventory, extraSlot, spawnX, spawnY, skinVariant, hair, hairDye, hairColor, pantsColor, shirtColor, underShirtColor, shoeColor, hideVisuals, skinColor, eyeColor, questsCompleted, usingBiomeTorches, happyFunTorchTime, unlockedBiomeTorches, currentLoadoutIndex, ateArtisanBread, usedAegisCrystal, usedAegisFruit, usedArcaneCrystal, usedGalaxyPearl, usedGummyWorm, usedAmbrosia, unlockedSuperCart, enabledSuperCart) VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22, @23, @24, @25, @26, @27, @28, @29, @30, @31, @32, @33, @34, @35);",
player.Account.ID,
playerData.health,
playerData.maxHealth,
Expand Down Expand Up @@ -304,7 +308,10 @@ public bool InsertSpecificPlayerData(TSPlayer player, PlayerData data)
playerData.usedGummyWorm,
playerData.usedAmbrosia,
playerData.unlockedSuperCart,
playerData.enabledSuperCart);
playerData.enabledSuperCart,
playerData.deathsPVE,
playerData.deathsPVP
);
return true;
}
catch (Exception ex)
Expand All @@ -317,7 +324,7 @@ public bool InsertSpecificPlayerData(TSPlayer player, PlayerData data)
try
{
database.Query(
"UPDATE tsCharacter SET Health = @0, MaxHealth = @1, Mana = @2, MaxMana = @3, Inventory = @4, spawnX = @6, spawnY = @7, hair = @8, hairDye = @9, hairColor = @10, pantsColor = @11, shirtColor = @12, underShirtColor = @13, shoeColor = @14, hideVisuals = @15, skinColor = @16, eyeColor = @17, questsCompleted = @18, skinVariant = @19, extraSlot = @20, usingBiomeTorches = @21, happyFunTorchTime = @22, unlockedBiomeTorches = @23, currentLoadoutIndex = @24, ateArtisanBread = @25, usedAegisCrystal = @26, usedAegisFruit = @27, usedArcaneCrystal = @28, usedGalaxyPearl = @29, usedGummyWorm = @30, usedAmbrosia = @31, unlockedSuperCart = @32, enabledSuperCart = @33 WHERE Account = @5;",
"UPDATE tsCharacter SET Health = @0, MaxHealth = @1, Mana = @2, MaxMana = @3, Inventory = @4, spawnX = @6, spawnY = @7, hair = @8, hairDye = @9, hairColor = @10, pantsColor = @11, shirtColor = @12, underShirtColor = @13, shoeColor = @14, hideVisuals = @15, skinColor = @16, eyeColor = @17, questsCompleted = @18, skinVariant = @19, extraSlot = @20, usingBiomeTorches = @21, happyFunTorchTime = @22, unlockedBiomeTorches = @23, currentLoadoutIndex = @24, ateArtisanBread = @25, usedAegisCrystal = @26, usedAegisFruit = @27, usedArcaneCrystal = @28, usedGalaxyPearl = @29, usedGummyWorm = @30, usedAmbrosia = @31, unlockedSuperCart = @32, enabledSuperCart = @33, deathsPVE = @34, deathsPVP = @35 WHERE Account = @5;",
playerData.health,
playerData.maxHealth,
playerData.mana,
Expand Down Expand Up @@ -351,7 +358,10 @@ public bool InsertSpecificPlayerData(TSPlayer player, PlayerData data)
playerData.usedGummyWorm,
playerData.usedAmbrosia,
playerData.unlockedSuperCart,
playerData.enabledSuperCart);
playerData.enabledSuperCart,
playerData.deathsPVE,
playerData.deathsPVP
);
return true;
}
catch (Exception ex)
Expand Down
9 changes: 9 additions & 0 deletions TShockAPI/GetDataHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4325,6 +4325,15 @@ private static bool HandlePlayerKillMeV2(GetDataHandlerArgs args)
args.Player.Dead = true;
args.Player.RespawnTimer = TShock.Config.Settings.RespawnSeconds;

if (Main.ServerSideCharacter && !args.Player.HasPermission(Permissions.bypassssc))
{
if (pvp)
{
args.Player.sscDeathsPVP++;
}
args.Player.sscDeathsPVE++;
}

foreach (NPC npc in Main.npc)
{
if (npc.active && (npc.boss || npc.type == 13 || npc.type == 14 || npc.type == 15) &&
Expand Down
6 changes: 6 additions & 0 deletions TShockAPI/PlayerData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public class PlayerData
public int usedAmbrosia;
public int unlockedSuperCart;
public int enabledSuperCart;
public int deathsPVE;
public int deathsPVP;

/// <summary>
/// Sets the default values for the inventory.
Expand Down Expand Up @@ -152,6 +154,8 @@ public void CopyCharacter(TSPlayer player)
this.usedAmbrosia = player.TPlayer.usedAmbrosia ? 1 : 0;
this.unlockedSuperCart = player.TPlayer.unlockedSuperCart ? 1 : 0;
this.enabledSuperCart = player.TPlayer.enabledSuperCart ? 1 : 0;
this.deathsPVE = player.TPlayer.numberOfDeathsPVE;
this.deathsPVP = player.TPlayer.numberOfDeathsPVP;

Item[] inventory = player.TPlayer.inventory;
Item[] armor = player.TPlayer.armor;
Expand Down Expand Up @@ -293,6 +297,8 @@ public void RestoreCharacter(TSPlayer player)
player.TPlayer.usedAmbrosia = this.usedAmbrosia == 1;
player.TPlayer.unlockedSuperCart = this.unlockedSuperCart == 1;
player.TPlayer.enabledSuperCart = this.enabledSuperCart == 1;
player.sscDeathsPVE = this.deathsPVE;
player.sscDeathsPVP = this.deathsPVP;

if (extraSlot != null)
player.TPlayer.extraAccessory = extraSlot.Value == 1 ? true : false;
Expand Down
42 changes: 42 additions & 0 deletions TShockAPI/TSPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,48 @@ public int RespawnTimer
/// <summary>Determines if the player has finished the handshake (Sent all necessary packets for connection, such as Request World Data, Spawn Player, etc). A normal client would do all of this no problem.</summary>
public bool FinishedHandshake = false;

/// <summary>Server-side character's recorded death count.</summary>
public int sscDeathsPVE = 0;

/// <summary>Server-side character's recorded PVP death count.</summary>
public int sscDeathsPVP = 0;

/// <summary>
/// Gets the player's total death count.
/// If server-side characters are enabled and player doesn't have bypass permission,
/// returns the server-stored value; otherwise returns the client's value.
/// </summary>
public int DeathsPVE
{
get
{
if (Main.ServerSideCharacter && !this.HasPermission(Permissions.bypassssc))
{
return sscDeathsPVE;
}

return this.TPlayer.numberOfDeathsPVE;
}
}

/// <summary>
/// Gets the player's total PVP death count.
/// If server-side characters are enabled and player doesn't have bypass permission,
/// returns the server-stored value; otherwise returns the client's value.
/// </summary>
public int DeathsPVP
{
get
{
if (Main.ServerSideCharacter && !this.HasPermission(Permissions.bypassssc))
{
return sscDeathsPVP;
}

return this.TPlayer.numberOfDeathsPVP;
}
}

/// <summary>Checks to see if active throttling is happening on events by Bouncer. Rejects repeated events by malicious clients in a short window.</summary>
/// <returns>If the player is currently being throttled by Bouncer, or not.</returns>
public bool IsBouncerThrottled()
Expand Down
Loading