Merge remote-tracking branch 'upstream/general-devel' into docker

This commit is contained in:
Joseph Goh 2022-10-23 07:06:01 +08:00
commit 7f15146217
No known key found for this signature in database
GPG key ID: 0C83392A0999DD5A
11 changed files with 562 additions and 103 deletions

View file

@ -779,6 +779,33 @@ namespace TShockAPI
return; return;
} }
// We need to emulate the checks done in Player.TrySwitchingLoadout, because otherwise the server is not allowed to sync the
// loadout index to the player, causing catastrophic desync.
// The player must not be dead, using an item, or CC'd to switch loadouts.
// FIXME: There is always the chance that in-between the time we check these requirements on the server, and the loadout sync
// packet reaches the client, that the client state has changed, causing the loadout sync to be rejected, even though
// we expected it to succeed.
if (args.TPlayer.dead)
{
args.Player.SendErrorMessage(GetString("You cannot login whilst dead."));
return;
}
// FIXME: This check is not correct -- even though we reject PlayerAnimation whilst disabled, we don't re-sync it to the client,
// meaning these will still be set on the client, and they WILL reject the loadout sync.
if (args.TPlayer.itemTime > 0 || args.TPlayer.itemAnimation > 0)
{
args.Player.SendErrorMessage(GetString("You cannot login whilst using an item."));
return;
}
if (args.TPlayer.CCed)
{
args.Player.SendErrorMessage(GetString("You cannot login whilst crowd controlled."));
return;
}
UserAccount account = TShock.UserAccounts.GetUserAccountByName(args.Player.Name); UserAccount account = TShock.UserAccounts.GetUserAccountByName(args.Player.Name);
string password = ""; string password = "";
bool usingUUID = false; bool usingUUID = false;

View file

@ -58,7 +58,8 @@ namespace TShockAPI.DB
new SqlColumn("questsCompleted", MySqlDbType.Int32), new SqlColumn("questsCompleted", MySqlDbType.Int32),
new SqlColumn("usingBiomeTorches", MySqlDbType.Int32), new SqlColumn("usingBiomeTorches", MySqlDbType.Int32),
new SqlColumn("happyFunTorchTime", MySqlDbType.Int32), new SqlColumn("happyFunTorchTime", MySqlDbType.Int32),
new SqlColumn("unlockedBiomeTorches", MySqlDbType.Int32) new SqlColumn("unlockedBiomeTorches", MySqlDbType.Int32),
new SqlColumn("currentLoadoutIndex", MySqlDbType.Int32)
); );
var creator = new SqlTableCreator(db, var creator = new SqlTableCreator(db,
db.GetSqlType() == SqlType.Sqlite db.GetSqlType() == SqlType.Sqlite
@ -114,6 +115,7 @@ namespace TShockAPI.DB
playerData.usingBiomeTorches = reader.Get<int>("usingBiomeTorches"); playerData.usingBiomeTorches = reader.Get<int>("usingBiomeTorches");
playerData.happyFunTorchTime = reader.Get<int>("happyFunTorchTime"); playerData.happyFunTorchTime = reader.Get<int>("happyFunTorchTime");
playerData.unlockedBiomeTorches = reader.Get<int>("unlockedBiomeTorches"); playerData.unlockedBiomeTorches = reader.Get<int>("unlockedBiomeTorches");
playerData.currentLoadoutIndex = reader.Get<int>("currentLoadoutIndex");
return playerData; return playerData;
} }
} }
@ -180,8 +182,8 @@ namespace TShockAPI.DB
try try
{ {
database.Query( 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) 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);", "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) 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);",
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.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);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@ -194,8 +196,8 @@ namespace TShockAPI.DB
try try
{ {
database.Query( 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 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 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); 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);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@ -250,7 +252,7 @@ namespace TShockAPI.DB
try try
{ {
database.Query( 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) 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);", "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) 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);",
player.Account.ID, player.Account.ID,
playerData.health, playerData.health,
playerData.maxHealth, playerData.maxHealth,
@ -274,7 +276,8 @@ namespace TShockAPI.DB
playerData.questsCompleted, playerData.questsCompleted,
playerData.usingBiomeTorches, playerData.usingBiomeTorches,
playerData.happyFunTorchTime, playerData.happyFunTorchTime,
playerData.unlockedBiomeTorches); playerData.unlockedBiomeTorches,
playerData.currentLoadoutIndex);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@ -287,7 +290,7 @@ namespace TShockAPI.DB
try try
{ {
database.Query( 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 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 WHERE Account = @5;",
playerData.health, playerData.health,
playerData.maxHealth, playerData.maxHealth,
playerData.mana, playerData.mana,
@ -311,7 +314,8 @@ namespace TShockAPI.DB
playerData.extraSlot ?? 0, playerData.extraSlot ?? 0,
playerData.usingBiomeTorches, playerData.usingBiomeTorches,
playerData.happyFunTorchTime, playerData.happyFunTorchTime,
playerData.unlockedBiomeTorches); playerData.unlockedBiomeTorches,
playerData.currentLoadoutIndex);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)

View file

@ -4350,14 +4350,76 @@ namespace TShockAPI
if (loadoutIndex == args.TPlayer.CurrentLoadoutIndex) if (loadoutIndex == args.TPlayer.CurrentLoadoutIndex)
return false; return false;
if (args.Player.IsBeingDisabled()) if (loadoutIndex >= args.TPlayer.Loadouts.Length)
{ {
TShock.Log.ConsoleDebug("GetDataHandlers / HandleSyncLoadout rejected loadout index sync {0}", args.Player.Name); TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandleSyncLoadout rejected loadout index sync out of bounds {0}",
args.Player.Name));
NetMessage.SendData((int)PacketTypes.SyncLoadout, number: args.Player.Index, number2: args.TPlayer.CurrentLoadoutIndex); NetMessage.SendData((int)PacketTypes.SyncLoadout, number: args.Player.Index, number2: args.TPlayer.CurrentLoadoutIndex);
return true; return true;
} }
if (args.Player.IsBeingDisabled())
{
TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandleSyncLoadout rejected loadout index sync {0}", args.Player.Name));
NetMessage.SendData((int)PacketTypes.SyncLoadout, number: args.Player.Index, number2: args.TPlayer.CurrentLoadoutIndex);
return true;
}
// The client does not sync slot changes when changing loadouts, it only tells the server the loadout index changed,
// and the server will replicate the changes the client did. This means that PlayerData.StoreSlot is never called, so we need to
// swap around the PlayerData items ourself.
Tuple<int, int> GetArmorSlotsForLoadoutIndex(int index)
{
return index switch
{
0 => NetItem.Loadout1Armor,
1 => NetItem.Loadout2Armor,
2 => NetItem.Loadout3Armor
};
}
Tuple<int, int> GetDyeSlotsForLoadoutIndex(int index)
{
return index switch
{
0 => NetItem.Loadout1Dye,
1 => NetItem.Loadout2Dye,
2 => NetItem.Loadout3Dye
};
}
var (currentLoadoutArmorSlotStartIndex, _) = GetArmorSlotsForLoadoutIndex(args.TPlayer.CurrentLoadoutIndex);
var (currentLoadoutDyeSlotStartIndex, _) = GetDyeSlotsForLoadoutIndex(args.TPlayer.CurrentLoadoutIndex);
var (switchedLoadoutArmorSlotStartIndex, _) = GetArmorSlotsForLoadoutIndex(loadoutIndex);
var (switchedLoadoutDyeSlotStartIndex, _) = GetDyeSlotsForLoadoutIndex(loadoutIndex);
// Emulate what is seen in Player.TrySwitchingLoadout:
// - Swap the current loadout items with the player's equipment
// - Swap the switching loadout items with the player's equipment
// At the end of all of this:
// - The current loadout will contain the player's original equipment
// - The switched loadout will contain the current loadout's items
// - The player's equipment will contain the switched loadout's item
for (var i = 0; i < NetItem.LoadoutArmorSlots; i++)
Terraria.Utils.Swap(ref args.Player.PlayerData.inventory[currentLoadoutArmorSlotStartIndex + i],
ref args.Player.PlayerData.inventory[NetItem.ArmorIndex.Item1 + i]);
for (var i = 0; i < NetItem.LoadoutDyeSlots; i++)
Terraria.Utils.Swap(ref args.Player.PlayerData.inventory[currentLoadoutDyeSlotStartIndex + i],
ref args.Player.PlayerData.inventory[NetItem.DyeIndex.Item1 + i]);
for (var i = 0; i < NetItem.LoadoutArmorSlots; i++)
Terraria.Utils.Swap(ref args.Player.PlayerData.inventory[switchedLoadoutArmorSlotStartIndex + i],
ref args.Player.PlayerData.inventory[NetItem.ArmorIndex.Item1 + i]);
for (var i = 0; i < NetItem.LoadoutDyeSlots; i++)
Terraria.Utils.Swap(ref args.Player.PlayerData.inventory[switchedLoadoutDyeSlotStartIndex + i],
ref args.Player.PlayerData.inventory[NetItem.DyeIndex.Item1 + i]);
return false; return false;
} }

View file

@ -81,10 +81,22 @@ namespace TShockAPI
/// </summary> /// </summary>
public static readonly int TrashSlots = 1; public static readonly int TrashSlots = 1;
/// <summary>
/// The number of armor slots in a loadout.
/// </summary>
public static readonly int LoadoutArmorSlots = ArmorSlots;
/// <summary>
/// The number of dye slots in a loadout.
/// </summary>
public static readonly int LoadoutDyeSlots = DyeSlots;
/// <summary> /// <summary>
/// 180 - The inventory size (inventory, held item, armour, dies, coins, ammo, piggy, safe, and trash) /// 180 - The inventory size (inventory, held item, armour, dies, coins, ammo, piggy, safe, and trash)
/// </summary> /// </summary>
public static readonly int MaxInventory = InventorySlots + ArmorSlots + DyeSlots + MiscEquipSlots + MiscDyeSlots + PiggySlots + SafeSlots + ForgeSlots + VoidSlots + 1; public static readonly int MaxInventory = InventorySlots + ArmorSlots + DyeSlots + MiscEquipSlots + MiscDyeSlots + PiggySlots +
SafeSlots + ForgeSlots + VoidSlots + TrashSlots + (LoadoutArmorSlots * 3) +
(LoadoutDyeSlots * 3);
public static readonly Tuple<int, int> InventoryIndex = new Tuple<int, int>(0, InventorySlots); public static readonly Tuple<int, int> InventoryIndex = new Tuple<int, int>(0, InventorySlots);
public static readonly Tuple<int, int> ArmorIndex = new Tuple<int, int>(InventoryIndex.Item2, InventoryIndex.Item2 + ArmorSlots); public static readonly Tuple<int, int> ArmorIndex = new Tuple<int, int>(InventoryIndex.Item2, InventoryIndex.Item2 + ArmorSlots);
@ -97,6 +109,15 @@ namespace TShockAPI
public static readonly Tuple<int, int> ForgeIndex = new Tuple<int, int>(TrashIndex.Item2, TrashIndex.Item2 + ForgeSlots); public static readonly Tuple<int, int> ForgeIndex = new Tuple<int, int>(TrashIndex.Item2, TrashIndex.Item2 + ForgeSlots);
public static readonly Tuple<int, int> VoidIndex = new Tuple<int, int>(ForgeIndex.Item2, ForgeIndex.Item2 + VoidSlots); public static readonly Tuple<int, int> VoidIndex = new Tuple<int, int>(ForgeIndex.Item2, ForgeIndex.Item2 + VoidSlots);
public static readonly Tuple<int, int> Loadout1Armor = new Tuple<int, int>(VoidIndex.Item2, VoidIndex.Item2 + LoadoutArmorSlots);
public static readonly Tuple<int, int> Loadout1Dye = new Tuple<int, int>(Loadout1Armor.Item2, Loadout1Armor.Item2 + LoadoutDyeSlots);
public static readonly Tuple<int, int> Loadout2Armor = new Tuple<int, int>(Loadout1Dye.Item2, Loadout1Dye.Item2 + LoadoutArmorSlots);
public static readonly Tuple<int, int> Loadout2Dye = new Tuple<int, int>(Loadout2Armor.Item2, Loadout2Armor.Item2 + LoadoutDyeSlots);
public static readonly Tuple<int, int> Loadout3Armor = new Tuple<int, int>(Loadout2Dye.Item2, Loadout2Dye.Item2 + LoadoutArmorSlots);
public static readonly Tuple<int, int> Loadout3Dye = new Tuple<int, int>(Loadout3Armor.Item2, Loadout3Armor.Item2 + LoadoutDyeSlots);
[JsonProperty("netID")] [JsonProperty("netID")]
private int _netId; private int _netId;
[JsonProperty("prefix")] [JsonProperty("prefix")]

View file

@ -52,6 +52,7 @@ namespace TShockAPI
public int usingBiomeTorches; public int usingBiomeTorches;
public int happyFunTorchTime; public int happyFunTorchTime;
public int unlockedBiomeTorches; public int unlockedBiomeTorches;
public int currentLoadoutIndex;
public PlayerData(TSPlayer player) public PlayerData(TSPlayer player)
{ {
@ -120,6 +121,7 @@ namespace TShockAPI
this.usingBiomeTorches = player.TPlayer.UsingBiomeTorches ? 1 : 0; this.usingBiomeTorches = player.TPlayer.UsingBiomeTorches ? 1 : 0;
this.happyFunTorchTime = player.TPlayer.happyFunTorchTime ? 1 : 0; this.happyFunTorchTime = player.TPlayer.happyFunTorchTime ? 1 : 0;
this.unlockedBiomeTorches = player.TPlayer.unlockedBiomeTorches ? 1 : 0; this.unlockedBiomeTorches = player.TPlayer.unlockedBiomeTorches ? 1 : 0;
this.currentLoadoutIndex = player.TPlayer.CurrentLoadoutIndex;
Item[] inventory = player.TPlayer.inventory; Item[] inventory = player.TPlayer.inventory;
Item[] armor = player.TPlayer.armor; Item[] armor = player.TPlayer.armor;
@ -131,6 +133,12 @@ namespace TShockAPI
Item[] forge = player.TPlayer.bank3.item; Item[] forge = player.TPlayer.bank3.item;
Item[] voidVault = player.TPlayer.bank4.item; Item[] voidVault = player.TPlayer.bank4.item;
Item trash = player.TPlayer.trashItem; Item trash = player.TPlayer.trashItem;
Item[] loadout1Armor = player.TPlayer.Loadouts[0].Armor;
Item[] loadout1Dye = player.TPlayer.Loadouts[0].Dye;
Item[] loadout2Armor = player.TPlayer.Loadouts[1].Armor;
Item[] loadout2Dye = player.TPlayer.Loadouts[1].Dye;
Item[] loadout3Armor = player.TPlayer.Loadouts[2].Armor;
Item[] loadout3Dye = player.TPlayer.Loadouts[2].Dye;
for (int i = 0; i < NetItem.MaxInventory; i++) for (int i = 0; i < NetItem.MaxInventory; i++)
{ {
@ -186,12 +194,42 @@ namespace TShockAPI
var index = i - NetItem.ForgeIndex.Item1; var index = i - NetItem.ForgeIndex.Item1;
this.inventory[i] = (NetItem)forge[index]; this.inventory[i] = (NetItem)forge[index];
} }
else else if(i < NetItem.VoidIndex.Item2)
{ {
//220 //220
var index = i - NetItem.VoidIndex.Item1; var index = i - NetItem.VoidIndex.Item1;
this.inventory[i] = (NetItem)voidVault[index]; this.inventory[i] = (NetItem)voidVault[index];
} }
else if(i < NetItem.Loadout1Armor.Item2)
{
var index = i - NetItem.Loadout1Armor.Item1;
this.inventory[i] = (NetItem)loadout1Armor[index];
}
else if(i < NetItem.Loadout1Dye.Item2)
{
var index = i - NetItem.Loadout1Dye.Item1;
this.inventory[i] = (NetItem)loadout1Dye[index];
}
else if(i < NetItem.Loadout2Armor.Item2)
{
var index = i - NetItem.Loadout2Armor.Item1;
this.inventory[i] = (NetItem)loadout2Armor[index];
}
else if(i < NetItem.Loadout2Dye.Item2)
{
var index = i - NetItem.Loadout2Dye.Item1;
this.inventory[i] = (NetItem)loadout2Dye[index];
}
else if(i < NetItem.Loadout3Armor.Item2)
{
var index = i - NetItem.Loadout3Armor.Item1;
this.inventory[i] = (NetItem)loadout3Armor[index];
}
else if(i < NetItem.Loadout3Dye.Item2)
{
var index = i - NetItem.Loadout3Dye.Item1;
this.inventory[i] = (NetItem)loadout3Dye[index];
}
} }
} }
@ -217,6 +255,7 @@ namespace TShockAPI
player.TPlayer.UsingBiomeTorches = this.usingBiomeTorches == 1; player.TPlayer.UsingBiomeTorches = this.usingBiomeTorches == 1;
player.TPlayer.happyFunTorchTime = this.happyFunTorchTime == 1; player.TPlayer.happyFunTorchTime = this.happyFunTorchTime == 1;
player.TPlayer.unlockedBiomeTorches = this.unlockedBiomeTorches == 1; player.TPlayer.unlockedBiomeTorches = this.unlockedBiomeTorches == 1;
player.TPlayer.CurrentLoadoutIndex = this.currentLoadoutIndex;
if (extraSlot != null) if (extraSlot != null)
player.TPlayer.extraAccessory = extraSlot.Value == 1 ? true : false; player.TPlayer.extraAccessory = extraSlot.Value == 1 ? true : false;
@ -353,7 +392,7 @@ namespace TShockAPI
player.TPlayer.bank3.item[index].Prefix((byte)this.inventory[i].PrefixId); player.TPlayer.bank3.item[index].Prefix((byte)this.inventory[i].PrefixId);
} }
} }
else else if (i < NetItem.VoidIndex.Item2)
{ {
//260 //260
var index = i - NetItem.VoidIndex.Item1; var index = i - NetItem.VoidIndex.Item1;
@ -365,7 +404,80 @@ namespace TShockAPI
player.TPlayer.bank4.item[index].Prefix((byte)this.inventory[i].PrefixId); player.TPlayer.bank4.item[index].Prefix((byte)this.inventory[i].PrefixId);
} }
} }
else if (i < NetItem.Loadout1Armor.Item2)
{
var index = i - NetItem.Loadout1Armor.Item1;
player.TPlayer.Loadouts[0].Armor[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.Loadouts[0].Armor[index].netID != 0)
{
player.TPlayer.Loadouts[0].Armor[index].stack = this.inventory[i].Stack;
player.TPlayer.Loadouts[0].Armor[index].Prefix((byte)this.inventory[i].PrefixId);
} }
}
else if (i < NetItem.Loadout1Dye.Item2)
{
var index = i - NetItem.Loadout1Dye.Item1;
player.TPlayer.Loadouts[0].Dye[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.Loadouts[0].Dye[index].netID != 0)
{
player.TPlayer.Loadouts[0].Dye[index].stack = this.inventory[i].Stack;
player.TPlayer.Loadouts[0].Dye[index].Prefix((byte)this.inventory[i].PrefixId);
}
}
else if (i < NetItem.Loadout2Armor.Item2)
{
var index = i - NetItem.Loadout2Armor.Item1;
player.TPlayer.Loadouts[1].Armor[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.Loadouts[1].Armor[index].netID != 0)
{
player.TPlayer.Loadouts[1].Armor[index].stack = this.inventory[i].Stack;
player.TPlayer.Loadouts[1].Armor[index].Prefix((byte)this.inventory[i].PrefixId);
}
}
else if (i < NetItem.Loadout2Dye.Item2)
{
var index = i - NetItem.Loadout2Dye.Item1;
player.TPlayer.Loadouts[1].Dye[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.Loadouts[1].Dye[index].netID != 0)
{
player.TPlayer.Loadouts[1].Dye[index].stack = this.inventory[i].Stack;
player.TPlayer.Loadouts[1].Dye[index].Prefix((byte)this.inventory[i].PrefixId);
}
}
else if (i < NetItem.Loadout3Armor.Item2)
{
var index = i - NetItem.Loadout3Armor.Item1;
player.TPlayer.Loadouts[2].Armor[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.Loadouts[2].Armor[index].netID != 0)
{
player.TPlayer.Loadouts[2].Armor[index].stack = this.inventory[i].Stack;
player.TPlayer.Loadouts[2].Armor[index].Prefix((byte)this.inventory[i].PrefixId);
}
}
else if (i < NetItem.Loadout3Dye.Item2)
{
var index = i - NetItem.Loadout3Dye.Item1;
player.TPlayer.Loadouts[2].Dye[index].netDefaults(this.inventory[i].NetId);
if (player.TPlayer.Loadouts[2].Dye[index].netID != 0)
{
player.TPlayer.Loadouts[2].Dye[index].stack = this.inventory[i].Stack;
player.TPlayer.Loadouts[2].Dye[index].Prefix((byte)this.inventory[i].PrefixId);
}
}
}
// Just like in MessageBuffer when the client receives a ContinueConnecting, let's sync the CurrentLoadoutIndex _before_ any of
// the items.
// This is sent to everyone BUT this player, and then ONLY this player. When using UUID login, it is too soon for the server to
// broadcast packets to this client.
NetMessage.SendData((int)PacketTypes.SyncLoadout, remoteClient: player.Index, number: player.Index, number2: player.TPlayer.CurrentLoadoutIndex);
NetMessage.SendData((int)PacketTypes.SyncLoadout, ignoreClient: player.Index, number: player.Index, number2: player.TPlayer.CurrentLoadoutIndex);
float slot = 0f; float slot = 0f;
for (int k = 0; k < NetItem.InventorySlots; k++) for (int k = 0; k < NetItem.InventorySlots; k++)
@ -414,6 +526,36 @@ namespace TShockAPI
NetMessage.SendData(5, -1, -1, NetworkText.FromLiteral(Main.player[player.Index].bank4.item[k].Name), player.Index, slot, (float)Main.player[player.Index].bank4.item[k].prefix); NetMessage.SendData(5, -1, -1, NetworkText.FromLiteral(Main.player[player.Index].bank4.item[k].Name), player.Index, slot, (float)Main.player[player.Index].bank4.item[k].prefix);
slot++; slot++;
} }
for (int k = 0; k < NetItem.LoadoutArmorSlots; k++)
{
NetMessage.SendData(5, -1, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[0].Armor[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[0].Armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutDyeSlots; k++)
{
NetMessage.SendData(5, -1, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[0].Dye[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[0].Dye[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutArmorSlots; k++)
{
NetMessage.SendData(5, -1, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[1].Armor[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[1].Armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutDyeSlots; k++)
{
NetMessage.SendData(5, -1, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[1].Dye[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[1].Dye[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutArmorSlots; k++)
{
NetMessage.SendData(5, -1, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[2].Armor[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[2].Armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutDyeSlots; k++)
{
NetMessage.SendData(5, -1, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[1].Dye[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[2].Dye[k].prefix);
slot++;
}
NetMessage.SendData(4, -1, -1, NetworkText.FromLiteral(player.Name), player.Index, 0f, 0f, 0f, 0); NetMessage.SendData(4, -1, -1, NetworkText.FromLiteral(player.Name), player.Index, 0f, 0f, 0f, 0);
@ -467,6 +609,36 @@ namespace TShockAPI
NetMessage.SendData(5, player.Index, -1, NetworkText.FromLiteral(Main.player[player.Index].bank4.item[k].Name), player.Index, slot, (float)Main.player[player.Index].bank4.item[k].prefix); NetMessage.SendData(5, player.Index, -1, NetworkText.FromLiteral(Main.player[player.Index].bank4.item[k].Name), player.Index, slot, (float)Main.player[player.Index].bank4.item[k].prefix);
slot++; slot++;
} }
for (int k = 0; k < NetItem.LoadoutArmorSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[0].Armor[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[0].Armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutDyeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[0].Dye[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[0].Dye[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutArmorSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[1].Armor[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[1].Armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutDyeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[1].Dye[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[1].Dye[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutArmorSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[2].Armor[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[2].Armor[k].prefix);
slot++;
}
for (int k = 0; k < NetItem.LoadoutDyeSlots; k++)
{
NetMessage.SendData(5, player.Index, -1, NetworkText.FromLiteral(Main.player[player.Index].Loadouts[2].Dye[k].Name), player.Index, slot, (float)Main.player[player.Index].Loadouts[2].Dye[k].prefix);
slot++;
}

View file

@ -386,6 +386,12 @@ namespace TShockAPI
Item[] safe = TPlayer.bank2.item; Item[] safe = TPlayer.bank2.item;
Item[] forge = TPlayer.bank3.item; Item[] forge = TPlayer.bank3.item;
Item[] voidVault = TPlayer.bank4.item; Item[] voidVault = TPlayer.bank4.item;
Item[] loadout1Armor = TPlayer.Loadouts[0].Armor;
Item[] loadout1Dye = TPlayer.Loadouts[0].Dye;
Item[] loadout2Armor = TPlayer.Loadouts[1].Armor;
Item[] loadout2Dye = TPlayer.Loadouts[1].Dye;
Item[] loadout3Armor = TPlayer.Loadouts[2].Armor;
Item[] loadout3Dye = TPlayer.Loadouts[2].Dye;
Item trash = TPlayer.trashItem; Item trash = TPlayer.trashItem;
for (int i = 0; i < NetItem.MaxInventory; i++) for (int i = 0; i < NetItem.MaxInventory; i++)
@ -594,7 +600,126 @@ namespace TShockAPI
} }
} }
} }
else if (i < NetItem.Loadout1Armor.Item2)
{
var index = i - NetItem.Loadout1Armor.Item1;
Item item = new Item();
if (loadout1Armor[index] != null && loadout1Armor[index].netID != 0)
{
item.netDefaults(loadout1Armor[index].netID);
item.Prefix(loadout1Armor[index].prefix);
item.AffixName();
if (loadout1Armor[index].stack > item.maxStack || loadout1Armor[index].stack < 0)
{
check = true;
if (shouldWarnPlayer)
{
SendErrorMessage(GetString("Stack cheat detected. Remove Loadout 1 item {0} ({1}) and then rejoin.", item.Name, loadout1Armor[index].stack));
}
}
}
}
else if (i < NetItem.Loadout1Dye.Item2)
{
var index = i - NetItem.Loadout1Dye.Item1;
Item item = new Item();
if (loadout1Dye[index] != null && loadout1Dye[index].netID != 0)
{
item.netDefaults(loadout1Dye[index].netID);
item.Prefix(loadout1Dye[index].prefix);
item.AffixName();
if (loadout1Dye[index].stack > item.maxStack || loadout1Dye[index].stack < 0)
{
check = true;
if (shouldWarnPlayer)
{
SendErrorMessage(GetString("Stack cheat detected. Remove Loadout 1 item {0} ({1}) and then rejoin.", item.Name, loadout1Dye[index].stack));
}
}
}
}
else if (i < NetItem.Loadout2Armor.Item2)
{
var index = i - NetItem.Loadout2Armor.Item1;
Item item = new Item();
if (loadout2Armor[index] != null && loadout2Armor[index].netID != 0)
{
item.netDefaults(loadout2Armor[index].netID);
item.Prefix(loadout2Armor[index].prefix);
item.AffixName();
if (loadout2Armor[index].stack > item.maxStack || loadout2Armor[index].stack < 0)
{
check = true;
if (shouldWarnPlayer)
{
SendErrorMessage(GetString("Stack cheat detected. Remove Loadout 2 item {0} ({1}) and then rejoin.", item.Name, loadout2Armor[index].stack));
}
}
}
}
else if (i < NetItem.Loadout2Dye.Item2)
{
var index = i - NetItem.Loadout2Dye.Item1;
Item item = new Item();
if (loadout2Dye[index] != null && loadout2Dye[index].netID != 0)
{
item.netDefaults(loadout2Dye[index].netID);
item.Prefix(loadout2Dye[index].prefix);
item.AffixName();
if (loadout2Dye[index].stack > item.maxStack || loadout2Dye[index].stack < 0)
{
check = true;
if (shouldWarnPlayer)
{
SendErrorMessage(GetString("Stack cheat detected. Remove Loadout 2 item {0} ({1}) and then rejoin.", item.Name, loadout2Dye[index].stack));
}
}
}
}
else if (i < NetItem.Loadout3Armor.Item2)
{
var index = i - NetItem.Loadout3Armor.Item1;
Item item = new Item();
if (loadout3Armor[index] != null && loadout3Armor[index].netID != 0)
{
item.netDefaults(loadout3Armor[index].netID);
item.Prefix(loadout3Armor[index].prefix);
item.AffixName();
if (loadout3Armor[index].stack > item.maxStack || loadout3Armor[index].stack < 0)
{
check = true;
if (shouldWarnPlayer)
{
SendErrorMessage(GetString("Stack cheat detected. Remove Loadout 3 item {0} ({1}) and then rejoin.", item.Name, loadout3Armor[index].stack));
}
}
}
}
else if (i < NetItem.Loadout3Dye.Item2)
{
var index = i - NetItem.Loadout3Dye.Item1;
Item item = new Item();
if (loadout3Dye[index] != null && loadout3Dye[index].netID != 0)
{
item.netDefaults(loadout3Dye[index].netID);
item.Prefix(loadout3Dye[index].prefix);
item.AffixName();
if (loadout3Dye[index].stack > item.maxStack || loadout3Dye[index].stack < 0)
{
check = true;
if (shouldWarnPlayer)
{
SendErrorMessage(GetString("Stack cheat detected. Remove Loadout 3 item {0} ({1}) and then rejoin.", item.Name, loadout3Dye[index].stack));
}
}
}
}
} }
return check; return check;

View file

@ -1605,7 +1605,7 @@ namespace TShockAPI
} }
if ((player.State < 10 || player.Dead) && (int)type > 12 && (int)type != 16 && (int)type != 42 && (int)type != 50 && if ((player.State < 10 || player.Dead) && (int)type > 12 && (int)type != 16 && (int)type != 42 && (int)type != 50 &&
(int)type != 38 && (int)type != 21 && (int)type != 22) (int)type != 38 && (int)type != 21 && (int)type != 22 && type != PacketTypes.SyncLoadout)
{ {
e.Handled = true; e.Handled = true;
return; return;

View file

@ -18,7 +18,7 @@
Also, be sure to release on github with the exact assembly version tag as below Also, be sure to release on github with the exact assembly version tag as below
so that the update manager works correctly (via the Github releases api and mimic) so that the update manager works correctly (via the Github releases api and mimic)
--> -->
<Version>5.0.0-beta.0.5</Version> <Version>5.0.0-beta.0.6</Version>
<AssemblyTitle>TShock for Terraria</AssemblyTitle> <AssemblyTitle>TShock for Terraria</AssemblyTitle>
<Company>Pryaxis &amp; TShock Contributors</Company> <Company>Pryaxis &amp; TShock Contributors</Company>
<Product>TShockAPI</Product> <Product>TShockAPI</Product>

View file

@ -64,8 +64,12 @@ Use past tense when adding new entries; sign your name off when you add or chang
* Added an internationalization system. The base for the i18n system was built by Janet Blackquill ([@pontaoski](https://github.com/pontaoski)). A small donation in her honor was made to the [KDE project](https://kde.org/) as a thankyou for this work. This also includes the `TSHOCK_LANGUAGE` environment variable. Setting `TSHOCK_LANGUAGE=tok` will enable a small number of [Toki Pona](https://tokipona.org/) translations as a proof-of-concept. (@pontaoski) * Added an internationalization system. The base for the i18n system was built by Janet Blackquill ([@pontaoski](https://github.com/pontaoski)). A small donation in her honor was made to the [KDE project](https://kde.org/) as a thankyou for this work. This also includes the `TSHOCK_LANGUAGE` environment variable. Setting `TSHOCK_LANGUAGE=tok` will enable a small number of [Toki Pona](https://tokipona.org/) translations as a proof-of-concept. (@pontaoski)
* Added support for Terraria 1.4.4.6, through OTAPI 3.1.5. (@SignatureBeef) * Added support for Terraria 1.4.4.6, through OTAPI 3.1.5. (@SignatureBeef)
* Added GeoIP.dat back to the included list of files. (@SignatureBeef) * Added GeoIP.dat back to the included list of files. (@SignatureBeef)
* Allow loadouts to properly sync by allowing the `SyncLoadout` packet during early connection. (@drunderscore)
* Introduced support for loadouts, and saving the current loadout index to SSC. Both `NetItem` and `PlayerData` were modified to support this. (@drunderscore)
* Check loadout slots for hacked item stacks. (@drunderscore)
* Dockerize TShock (@PotatoCider) * Dockerize TShock (@PotatoCider)
## TShock 4.5.18 ## TShock 4.5.18
* Fixed `TSPlayer.GiveItem` not working if the player is in lava. (@PotatoCider) * Fixed `TSPlayer.GiveItem` not working if the player is in lava. (@PotatoCider)
* Only allow using Teleportation Potions, Magic Conch, and Demon Conch whilst holding them. (@drunderscore) * Only allow using Teleportation Potions, Magic Conch, and Demon Conch whilst holding them. (@drunderscore)

View file

@ -6,6 +6,12 @@ When enabled in TShock, SSC takes over control of inventory management for a pla
For developers, TShock's SSC implementation should be considered the reference implementation. More things are possible with this system than what TShock does. For developers, TShock's SSC implementation should be considered the reference implementation. More things are possible with this system than what TShock does.
## Limitations
In TShock 5 (Terraria 1.4.4.x), loadouts have some caveats. **Data loss or corruption may occur if you aren't careful.** If a player is de-buffed, crowd-controlled, or dead, and the player's client will ignore the loadout synchronization packet. TShock's `Disable()` method, webbing, and other de-buffs may cause desyncs between the server and client. Further, if players use items or otherwise become debuffed, they may also desynchronize. Because of this, we strongly advise telling players to be careful and not use items during loadout changes, or they risk data loss or corruption.
Admins that use `Dimensions` or other proxy tools that join multiple servers together may experience this if those proxies disable or de-buff players during the server switch window, before the player is logged in and synchronized.
## Setting up SSC ## Setting up SSC
To setup SSC, simply change `Enabled` to `true` in `sscconfig.json` in the `tshock` config folder. To setup SSC, simply change `Enabled` to `true` in `sscconfig.json` in the `tshock` config folder.
@ -90,7 +96,3 @@ If a TShock player has `tshock.ignore.ssc`, and `WarnPlayersAboutBypassPermissio
Sometimes, you want to import player data from players that join your server. For example, if you trust your friends not to bring hacked items in, you can import their data into the system. This is done with the `/uploadssc` command. Sometimes, you want to import player data from players that join your server. For example, if you trust your friends not to bring hacked items in, you can import their data into the system. This is done with the `/uploadssc` command.
The `/overridessc` command can be used to upload SSC data from a given player. The difference between this command is that `/uploadssc` uploads their data from when they joined, whereas `/overridessc` will just save whatever their current state is to the database. The `/overridessc` command can be used to upload SSC data from a given player. The difference between this command is that `/uploadssc` uploads their data from when they joined, whereas `/overridessc` will just save whatever their current state is to the database.
## Limitations
Currently, SSC does not support loadouts (1.4.4.x content).

View file

@ -1,8 +1,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TShock\n" "Project-Id-Version: TShock\n"
"POT-Creation-Date: 2022-10-22 08:09:52+0000\n" "POT-Creation-Date: 2022-10-22 21:54:33+0000\n"
"PO-Revision-Date: 2022-10-22 08:09:53+0000\n" "PO-Revision-Date: 2022-10-22 21:54:34+0000\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -10,13 +10,13 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: GetText.NET Extractor\n" "X-Generator: GetText.NET Extractor\n"
#: ../../TShockAPI/DB/CharacterManager.cs:174 #: ../../TShockAPI/DB/CharacterManager.cs:176
#, csharp-format #, csharp-format
msgctxt "{0} is a player name" msgctxt "{0} is a player name"
msgid "Skipping SSC save (due to tshock.ignore.ssc) for {0}" msgid "Skipping SSC save (due to tshock.ignore.ssc) for {0}"
msgstr "" msgstr ""
#: ../../TShockAPI/DB/CharacterManager.cs:244 #: ../../TShockAPI/DB/CharacterManager.cs:246
msgctxt "{0} is a player name" msgctxt "{0} is a player name"
msgid "Skipping SSC save (due to tshock.ignore.ssc) for {player.Account.Name}" msgid "Skipping SSC save (due to tshock.ignore.ssc) for {player.Account.Name}"
msgstr "" msgstr ""
@ -43,12 +43,12 @@ msgstr ""
msgid "\"{0}\" requested REST endpoint: {1}" msgid "\"{0}\" requested REST endpoint: {1}"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:940 #: ../../TShockAPI/Commands.cs:967
#, csharp-format #, csharp-format
msgid "{0} ({1}) changed the password for account {2}." msgid "{0} ({1}) changed the password for account {2}."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:950 #: ../../TShockAPI/Commands.cs:977
#, csharp-format #, csharp-format
msgid "{0} ({1}) failed to change the password for account {2}." msgid "{0} ({1}) failed to change the password for account {2}."
msgstr "" msgstr ""
@ -60,26 +60,26 @@ msgid ""
"automatically." "automatically."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1070 #: ../../TShockAPI/Commands.cs:1097
#, csharp-format #, csharp-format
msgid "{0} added account {1} to group {2}" msgid "{0} added account {1} to group {2}"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1028 #: ../../TShockAPI/Commands.cs:1055
msgid "{0} attempted to register for the account {1} but it was already taken." msgid "{0} attempted to register for the account {1} but it was already taken."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:869 #: ../../TShockAPI/Commands.cs:896
#, csharp-format #, csharp-format
msgid "{0} authenticated successfully as user: {1}." msgid "{0} authenticated successfully as user: {1}."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1144 #: ../../TShockAPI/Commands.cs:1171
#, csharp-format #, csharp-format
msgid "{0} changed account {1} to group {2}." msgid "{0} changed account {1} to group {2}."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1118 #: ../../TShockAPI/Commands.cs:1145
#, csharp-format #, csharp-format
msgid "{0} changed the password for account {1}" msgid "{0} changed the password for account {1}"
msgstr "" msgstr ""
@ -89,12 +89,12 @@ msgstr ""
msgid "{0} executed: {1}{2}." msgid "{0} executed: {1}{2}."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:894 #: ../../TShockAPI/Commands.cs:921
#, csharp-format #, csharp-format
msgid "{0} failed to authenticate as user: {1}" msgid "{0} failed to authenticate as user: {1}"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1150 #: ../../TShockAPI/Commands.cs:1177
#, csharp-format #, csharp-format
msgid "{0} has changed your group to {1}." msgid "{0} has changed your group to {1}."
msgstr "" msgstr ""
@ -111,12 +111,12 @@ msgid_plural "{killcount} NPCs have been killed."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: ../../TShockAPI/Commands.cs:1022 #: ../../TShockAPI/Commands.cs:1049
#, csharp-format #, csharp-format
msgid "{0} registered an account: \"{1}\"." msgid "{0} registered an account: \"{1}\"."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1096 #: ../../TShockAPI/Commands.cs:1123
#, csharp-format #, csharp-format
msgid "{0} successfully deleted account: {1}" msgid "{0} successfully deleted account: {1}"
msgstr "" msgstr ""
@ -126,38 +126,38 @@ msgstr ""
msgid "{0} tried to execute {1}{2}." msgid "{0} tried to execute {1}{2}."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:814 #: ../../TShockAPI/Commands.cs:841
#, csharp-format #, csharp-format
msgid "{0}login - Logs in using your UUID and character name." msgid "{0}login - Logs in using your UUID and character name."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:819 #: ../../TShockAPI/Commands.cs:846
#, csharp-format #, csharp-format
msgid "{0}login {1} - Logs in using your password and character name.password" msgid "{0}login {1} - Logs in using your password and character name.password"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:817 #: ../../TShockAPI/Commands.cs:844
#, csharp-format #, csharp-format
msgid "" msgid ""
"{0}login {1} {2} - Logs in using your username and password.usernamepassword" "{0}login {1} {2} - Logs in using your username and password.usernamepassword"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1169 #: ../../TShockAPI/Commands.cs:1196
#, csharp-format #, csharp-format
msgid "{0}user add username password group -- Adds a specified user" msgid "{0}user add username password group -- Adds a specified user"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1170 #: ../../TShockAPI/Commands.cs:1197
#, csharp-format #, csharp-format
msgid "{0}user del username -- Removes a specified user" msgid "{0}user del username -- Removes a specified user"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1172 #: ../../TShockAPI/Commands.cs:1199
#, csharp-format #, csharp-format
msgid "{0}user group username newgroup -- Changes a user's group" msgid "{0}user group username newgroup -- Changes a user's group"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1171 #: ../../TShockAPI/Commands.cs:1198
#, csharp-format #, csharp-format
msgid "{0}user password username newpassword -- Changes a user's password" msgid "{0}user password username newpassword -- Changes a user's password"
msgstr "" msgstr ""
@ -175,26 +175,26 @@ msgid ""
"and is at the RESTMaximumRequestsPerInterval threshold." "and is at the RESTMaximumRequestsPerInterval threshold."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:828 #: ../../TShockAPI/Commands.cs:855
msgid "A user account by that name does not exist." msgid "A user account by that name does not exist."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1010 #: ../../TShockAPI/Commands.cs:1037
#, csharp-format #, csharp-format
msgid "Account \"{0}\" has been registered." msgid "Account \"{0}\" has been registered."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1123 #: ../../TShockAPI/Commands.cs:1150
#, csharp-format #, csharp-format
msgid "Account {0} does not exist! Therefore, the password cannot be changed." msgid "Account {0} does not exist! Therefore, the password cannot be changed."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1069 #: ../../TShockAPI/Commands.cs:1096
#, csharp-format #, csharp-format
msgid "Account {0} has been added to group {1}!" msgid "Account {0} has been added to group {1}!"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1145 #: ../../TShockAPI/Commands.cs:1172
#, csharp-format #, csharp-format
msgid "Account {0} has been changed to group {1}." msgid "Account {0} has been changed to group {1}."
msgstr "" msgstr ""
@ -204,7 +204,7 @@ msgstr ""
msgid "Account needed! Please {0}register or {0}login to play!" msgid "Account needed! Please {0}register or {0}login to play!"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1095 #: ../../TShockAPI/Commands.cs:1122
msgid "Account removed successfully." msgid "Account removed successfully."
msgstr "" msgstr ""
@ -218,7 +218,7 @@ msgstr ""
msgid "AddUser SQL returned an error ({0})" msgid "AddUser SQL returned an error ({0})"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1187 #: ../../TShockAPI/Commands.cs:1214
#, csharp-format #, csharp-format
msgid "Allocated memory: {0}" msgid "Allocated memory: {0}"
msgstr "" msgstr ""
@ -259,7 +259,7 @@ msgstr ""
msgid "Anonymous requested REST endpoint: {0}" msgid "Anonymous requested REST endpoint: {0}"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:867 #: ../../TShockAPI/Commands.cs:894
#, csharp-format #, csharp-format
msgid "Authenticated as {0} successfully." msgid "Authenticated as {0} successfully."
msgstr "" msgstr ""
@ -293,7 +293,7 @@ msgstr ""
msgid "Backup Thread" msgid "Backup Thread"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:801 #: ../../TShockAPI/Commands.cs:828
msgid "Bad login attempt." msgid "Bad login attempt."
msgstr "" msgstr ""
@ -1460,6 +1460,18 @@ msgstr ""
msgid "Forces all liquids to update immediately." msgid "Forces all liquids to update immediately."
msgstr "" msgstr ""
#: ../../TShockAPI/GetDataHandlers.cs:4364
#, csharp-format
msgid "GetDataHandlers / HandleSyncLoadout rejected loadout index sync {0}"
msgstr ""
#: ../../TShockAPI/GetDataHandlers.cs:4355
#, csharp-format
msgid ""
"GetDataHandlers / HandleSyncLoadout rejected loadout index sync out of bounds "
"{0}"
msgstr ""
#: ../../TShockAPI/DB/UserManager.cs:291 #: ../../TShockAPI/DB/UserManager.cs:291
#, csharp-format #, csharp-format
msgid "GetUser SQL returned an error {0}" msgid "GetUser SQL returned an error {0}"
@ -1526,7 +1538,7 @@ msgstr ""
msgid "Group {0} does not exist" msgid "Group {0} does not exist"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1074 #: ../../TShockAPI/Commands.cs:1101
#, csharp-format #, csharp-format
msgid "Group {0} does not exist!" msgid "Group {0} does not exist!"
msgstr "" msgstr ""
@ -1589,7 +1601,7 @@ msgstr ""
msgid "Heals a player in HP and MP." msgid "Heals a player in HP and MP."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1199 #: ../../TShockAPI/Commands.cs:1226
#, csharp-format #, csharp-format
msgid "ID: {0}" msgid "ID: {0}"
msgstr "" msgstr ""
@ -1630,7 +1642,7 @@ msgid ""
"were disabled for to TShock so we can improve this!" "were disabled for to TShock so we can improve this!"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:821 #: ../../TShockAPI/Commands.cs:848
msgid "If you forgot your password, contact the administrator for help." msgid "If you forgot your password, contact the administrator for help."
msgstr "" msgstr ""
@ -1657,7 +1669,7 @@ msgstr ""
msgid "Infinite group parenting ({0})" msgid "Infinite group parenting ({0})"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1196 #: ../../TShockAPI/Commands.cs:1223
msgid "Information about the currently running world" msgid "Information about the currently running world"
msgstr "" msgstr ""
@ -1691,7 +1703,7 @@ msgstr ""
msgid "Invalid parent group {0} for group {1}." msgid "Invalid parent group {0} for group {1}."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:892 #: ../../TShockAPI/Commands.cs:919
msgid "Invalid password!" msgid "Invalid password!"
msgstr "" msgstr ""
@ -1704,7 +1716,7 @@ msgid ""
"Press any key to exit." "Press any key to exit."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1001 #: ../../TShockAPI/Commands.cs:1028
#, csharp-format #, csharp-format
msgid "Invalid syntax! Proper syntax: {0}register <password>" msgid "Invalid syntax! Proper syntax: {0}register <password>"
msgstr "" msgstr ""
@ -1714,8 +1726,8 @@ msgstr ""
msgid "Invalid Type: '{0}'" msgid "Invalid Type: '{0}'"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1043 #: ../../TShockAPI/Commands.cs:1070
#: ../../TShockAPI/Commands.cs:1176 #: ../../TShockAPI/Commands.cs:1203
#, csharp-format #, csharp-format
msgid "Invalid user syntax. Try {0}user help." msgid "Invalid user syntax. Try {0}user help."
msgstr "" msgstr ""
@ -1767,7 +1779,7 @@ msgstr ""
msgid "Lists commands or gives help on them." msgid "Lists commands or gives help on them."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:838 #: ../../TShockAPI/Commands.cs:865
msgid "Login attempt failed - see the message above." msgid "Login attempt failed - see the message above."
msgstr "" msgstr ""
@ -1779,7 +1791,7 @@ msgstr ""
msgid "Logs you out of your current account." msgid "Logs you out of your current account."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1191 #: ../../TShockAPI/Commands.cs:1218
#, csharp-format #, csharp-format
msgid "Machine name: {0}" msgid "Machine name: {0}"
msgstr "" msgstr ""
@ -1824,7 +1836,7 @@ msgstr ""
msgid "Manages user accounts." msgid "Manages user accounts."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1186 #: ../../TShockAPI/Commands.cs:1213
#, csharp-format #, csharp-format
msgid "Memory usage: {0}" msgid "Memory usage: {0}"
msgstr "" msgstr ""
@ -1843,7 +1855,7 @@ msgstr ""
msgid "Missing or invalid {0} parameter" msgid "Missing or invalid {0} parameter"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1201 #: ../../TShockAPI/Commands.cs:1228
#, csharp-format #, csharp-format
msgid "Mode: {0}" msgid "Mode: {0}"
msgstr "" msgstr ""
@ -1857,7 +1869,7 @@ msgstr ""
msgid "Multiple user accounts found for {0} '{1}'" msgid "Multiple user accounts found for {0} '{1}'"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1197 #: ../../TShockAPI/Commands.cs:1224
#, csharp-format #, csharp-format
msgid "Name: {0}" msgid "Name: {0}"
msgstr "" msgstr ""
@ -1905,7 +1917,7 @@ msgid ""
"Not authorized. User \"{0}\" has no access to use the specified API endpoint." "Not authorized. User \"{0}\" has no access to use the specified API endpoint."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:955 #: ../../TShockAPI/Commands.cs:982
#, csharp-format #, csharp-format
msgid "" msgid ""
"Not logged in or invalid syntax! Proper syntax: {0}password <oldpassword> " "Not logged in or invalid syntax! Proper syntax: {0}password <oldpassword> "
@ -1927,7 +1939,7 @@ msgstr ""
msgid "One of your UserIDs is not a usable integer: {0}" msgid "One of your UserIDs is not a usable integer: {0}"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1189 #: ../../TShockAPI/Commands.cs:1216
#, csharp-format #, csharp-format
msgid "Operating system: {0}" msgid "Operating system: {0}"
msgstr "" msgstr ""
@ -1941,14 +1953,14 @@ msgstr ""
msgid "Parenting group {0} to {1} would cause loops in the parent chain." msgid "Parenting group {0} to {1} would cause loops in the parent chain."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1127 #: ../../TShockAPI/Commands.cs:1154
#, csharp-format #, csharp-format
msgid "" msgid ""
"Password change attempt for {0} failed for an unknown reason. Check the " "Password change attempt for {0} failed for an unknown reason. Check the "
"server console for more details." "server console for more details."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1119 #: ../../TShockAPI/Commands.cs:1146
#, csharp-format #, csharp-format
msgid "Password change succeeded for {0}." msgid "Password change succeeded for {0}."
msgstr "" msgstr ""
@ -1959,21 +1971,21 @@ msgstr ""
msgid "Password must be at least {0} characters." msgid "Password must be at least {0} characters."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:944 #: ../../TShockAPI/Commands.cs:971
#: ../../TShockAPI/Commands.cs:981 #: ../../TShockAPI/Commands.cs:1008
#: ../../TShockAPI/Commands.cs:995 #: ../../TShockAPI/Commands.cs:1022
#: ../../TShockAPI/Commands.cs:1061 #: ../../TShockAPI/Commands.cs:1088
#: ../../TShockAPI/Commands.cs:1132 #: ../../TShockAPI/Commands.cs:1159
#, csharp-format #, csharp-format
msgid "Password must be greater than or equal to {0} characters." msgid "Password must be greater than or equal to {0} characters."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:961 #: ../../TShockAPI/Commands.cs:988
#, csharp-format #, csharp-format
msgid "PasswordUser returned an error: {0}" msgid "PasswordUser returned an error: {0}"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1202 #: ../../TShockAPI/Commands.cs:1229
#, csharp-format #, csharp-format
msgid "Path: {0}" msgid "Path: {0}"
msgstr "" msgstr ""
@ -2021,11 +2033,11 @@ msgstr ""
msgid "Player does not have permission to create projectile {0}." msgid "Player does not have permission to create projectile {0}."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:915 #: ../../TShockAPI/Commands.cs:942
msgid "Please close NPC windows before logging out." msgid "Please close NPC windows before logging out."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1027 #: ../../TShockAPI/Commands.cs:1054
msgid "Please try a different username." msgid "Please try a different username."
msgstr "" msgstr ""
@ -2038,7 +2050,7 @@ msgstr ""
msgid "Prevents a player from talking." msgid "Prevents a player from talking."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1190 #: ../../TShockAPI/Commands.cs:1217
#, csharp-format #, csharp-format
msgid "Proc count: {0}" msgid "Proc count: {0}"
msgstr "" msgstr ""
@ -2083,7 +2095,7 @@ msgstr ""
msgid "Registers you an account." msgid "Registers you an account."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1034 #: ../../TShockAPI/Commands.cs:1061
#, csharp-format #, csharp-format
msgid "RegisterUser returned an error: {0}" msgid "RegisterUser returned an error: {0}"
msgstr "" msgstr ""
@ -2148,7 +2160,7 @@ msgstr ""
msgid "Saves the world file." msgid "Saves the world file."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1200 #: ../../TShockAPI/Commands.cs:1227
#, csharp-format #, csharp-format
msgid "Seed: {0}" msgid "Seed: {0}"
msgstr "" msgstr ""
@ -2183,7 +2195,7 @@ msgstr ""
msgid "Server map saving..." msgid "Server map saving..."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:923 #: ../../TShockAPI/Commands.cs:950
msgid "Server side characters are enabled. You need to be logged-in to play." msgid "Server side characters are enabled. You need to be logged-in to play."
msgstr "" msgstr ""
@ -2263,7 +2275,7 @@ msgstr ""
msgid "Shuts down the server without saving." msgid "Shuts down the server without saving."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1198 #: ../../TShockAPI/Commands.cs:1225
#, csharp-format #, csharp-format
msgid "Size: {0}x{1}" msgid "Size: {0}x{1}"
msgstr "" msgstr ""
@ -2272,13 +2284,13 @@ msgstr ""
msgid "Slaps a player, dealing damage." msgid "Slaps a player, dealing damage."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1026 #: ../../TShockAPI/Commands.cs:1053
#, csharp-format #, csharp-format
msgid "Sorry, {0} was already taken by another person." msgid "Sorry, {0} was already taken by another person."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:960 #: ../../TShockAPI/Commands.cs:987
#: ../../TShockAPI/Commands.cs:1033 #: ../../TShockAPI/Commands.cs:1060
#, csharp-format #, csharp-format
msgid "Sorry, an error occurred: {0}." msgid "Sorry, an error occurred: {0}."
msgstr "" msgstr ""
@ -2317,6 +2329,24 @@ msgstr ""
msgid "Spreading water without holding a water bucket" msgid "Spreading water without holding a water bucket"
msgstr "" msgstr ""
#: ../../TShockAPI/TSPlayer.cs:618
#: ../../TShockAPI/TSPlayer.cs:638
#, csharp-format
msgid "Stack cheat detected. Remove Loadout 1 item {0} ({1}) and then rejoin."
msgstr ""
#: ../../TShockAPI/TSPlayer.cs:658
#: ../../TShockAPI/TSPlayer.cs:678
#, csharp-format
msgid "Stack cheat detected. Remove Loadout 2 item {0} ({1}) and then rejoin."
msgstr ""
#: ../../TShockAPI/TSPlayer.cs:698
#: ../../TShockAPI/TSPlayer.cs:718
#, csharp-format
msgid "Stack cheat detected. Remove Loadout 3 item {0} ({1}) and then rejoin."
msgstr ""
#: ../../TShockAPI/Rest/SecureRest.cs:167 #: ../../TShockAPI/Rest/SecureRest.cs:167
msgid "Successful login" msgid "Successful login"
msgstr "" msgstr ""
@ -2355,7 +2385,7 @@ msgstr ""
msgid "Temporarily sets another player's group." msgid "Temporarily sets another player's group."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1154 #: ../../TShockAPI/Commands.cs:1181
msgid "That group does not exist!" msgid "That group does not exist!"
msgstr "" msgstr ""
@ -2413,7 +2443,7 @@ msgstr ""
msgid "The specified token queued for destruction failed to be deleted." msgid "The specified token queued for destruction failed to be deleted."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1100 #: ../../TShockAPI/Commands.cs:1127
#, csharp-format #, csharp-format
msgid "The user {0} does not exist! Therefore, the account was not deleted!" msgid "The user {0} does not exist! Therefore, the account was not deleted!"
msgstr "" msgstr ""
@ -2430,7 +2460,7 @@ msgstr ""
msgid "The world's chest limit has been reached - unable to place more." msgid "The world's chest limit has been reached - unable to place more."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:900 #: ../../TShockAPI/Commands.cs:927
msgid "" msgid ""
"There was an error processing your login or authentication related request." "There was an error processing your login or authentication related request."
msgstr "" msgstr ""
@ -2485,22 +2515,22 @@ msgstr ""
msgid "Too many invalid login attempts." msgid "Too many invalid login attempts."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1188 #: ../../TShockAPI/Commands.cs:1215
#, csharp-format #, csharp-format
msgid "Total processor time: {0}" msgid "Total processor time: {0}"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1017 #: ../../TShockAPI/Commands.cs:1044
#, csharp-format #, csharp-format
msgid "Type {0}login \"{1}\" {2} to sign in to your account." msgid "Type {0}login \"{1}\" {2} to sign in to your account."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1019 #: ../../TShockAPI/Commands.cs:1046
#, csharp-format #, csharp-format
msgid "Type {0}login {1} to sign in to your account." msgid "Type {0}login {1} to sign in to your account."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1014 #: ../../TShockAPI/Commands.cs:1041
#, csharp-format #, csharp-format
msgid "Type {0}login to sign in to your account using your UUID." msgid "Type {0}login to sign in to your account using your UUID."
msgstr "" msgstr ""
@ -2533,22 +2563,22 @@ msgstr ""
msgid "User {0} '{1}' doesn't exist" msgid "User {0} '{1}' doesn't exist"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1078 #: ../../TShockAPI/Commands.cs:1105
#, csharp-format #, csharp-format
msgid "User {0} already exists!" msgid "User {0} already exists!"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1082 #: ../../TShockAPI/Commands.cs:1109
#, csharp-format #, csharp-format
msgid "User {0} could not be added, check console for details." msgid "User {0} could not be added, check console for details."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1162 #: ../../TShockAPI/Commands.cs:1189
#, csharp-format #, csharp-format
msgid "User {0} could not be added. Check console for details." msgid "User {0} could not be added. Check console for details."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1158 #: ../../TShockAPI/Commands.cs:1185
#, csharp-format #, csharp-format
msgid "User {0} does not exist!" msgid "User {0} does not exist!"
msgstr "" msgstr ""
@ -2563,7 +2593,7 @@ msgstr ""
msgid "User account {0} does not exist" msgid "User account {0} does not exist"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1168 #: ../../TShockAPI/Commands.cs:1195
msgid "User management command help:" msgid "User management command help:"
msgstr "" msgstr ""
@ -2591,7 +2621,7 @@ msgstr ""
msgid "Using banned water bucket without permissions" msgid "Using banned water bucket without permissions"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:888 #: ../../TShockAPI/Commands.cs:915
msgid "UUID does not match this character!" msgid "UUID does not match this character!"
msgstr "" msgstr ""
@ -2608,7 +2638,7 @@ msgstr ""
msgid "You are already logged in, and cannot login again." msgid "You are already logged in, and cannot login again."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:909 #: ../../TShockAPI/Commands.cs:936
msgid "You are not logged-in. Therefore, you cannot logout." msgid "You are not logged-in. Therefore, you cannot logout."
msgstr "" msgstr ""
@ -2622,6 +2652,18 @@ msgstr ""
msgid "You can't remove the default guest group." msgid "You can't remove the default guest group."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:805
msgid "You cannot login whilst crowd controlled."
msgstr ""
#: ../../TShockAPI/Commands.cs:791
msgid "You cannot login whilst dead."
msgstr ""
#: ../../TShockAPI/Commands.cs:799
msgid "You cannot login whilst using an item."
msgstr ""
#: ../../TShockAPI/Commands.cs:688 #: ../../TShockAPI/Commands.cs:688
msgid "You do not have access to this command." msgid "You do not have access to this command."
msgstr "" msgstr ""
@ -2722,7 +2764,7 @@ msgstr ""
msgid "You do not have permission to toggle godmode." msgid "You do not have permission to toggle godmode."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:949 #: ../../TShockAPI/Commands.cs:976
msgid "You failed to change your password!" msgid "You failed to change your password!"
msgstr "" msgstr ""
@ -2734,11 +2776,11 @@ msgstr ""
msgid "You have been remotely unmmuted" msgid "You have been remotely unmmuted"
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:920 #: ../../TShockAPI/Commands.cs:947
msgid "You have been successfully logged out of your account." msgid "You have been successfully logged out of your account."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:938 #: ../../TShockAPI/Commands.cs:965
msgid "You have successfully changed your password." msgid "You have successfully changed your password."
msgstr "" msgstr ""
@ -2769,7 +2811,7 @@ msgstr ""
msgid "Your database contains invalid UserIDs (they should be integers)." msgid "Your database contains invalid UserIDs (they should be integers)."
msgstr "" msgstr ""
#: ../../TShockAPI/Commands.cs:1011 #: ../../TShockAPI/Commands.cs:1038
#, csharp-format #, csharp-format
msgid "Your password is {0}." msgid "Your password is {0}."
msgstr "" msgstr ""