Merge branch 'general-devel' into patch-6

This commit is contained in:
Lucas Nicodemus 2020-05-30 00:11:18 -07:00 committed by GitHub
commit efeb8b6167
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 160 additions and 19 deletions

1
.github/FUNDING.yml vendored
View file

@ -1,3 +1,2 @@
# These are supported funding model platforms
custom: https://www.givedirectly.org/

View file

@ -3,16 +3,27 @@
This is the rolling changelog for TShock for Terraria. Use past tense when adding new entries; sign your name off when you add or change something. This should primarily be things like user changes, not necessarily codebase changes unless it's really relevant or large.
## Upcoming Release
* Fix pet licenses. (@Olink)
* Initial support for Journey mode in SSC worlds. (@Olink)
* Make TShock database MySQL 8 compatible by escaping column names in our IQueryBuilder code. (Name `Groups` is a reserved element in this version, which is used in our `Region` table.) (@Patrikkk)
* Reintroduce `-worldselectpath` per feedback from @fjfnaranjo. This command line argument should be used to specify the place where the interactive server startup will look for worlds to show on the world select screen. The original version of this argument, `-worldpath`, was removed because several game service providers have broken configurations that stop the server from running with an unhelpful error. This specific configuration was `-world` and `-worldpath`. In the new world, you can do the following:
* Fixed pet licenses. (@Olink)
* Added initial support for Journey mode in SSC worlds. (@Olink)
* Made TShock database MySQL 8 compatible by escaping column names in our IQueryBuilder code. (Name `Groups` is a reserved element in this version, which is used in our `Region` table.) (@Patrikkk)
* Reintroduced `-worldselectpath` per feedback from @fjfnaranjo. This command line argument should be used to specify the place where the interactive server startup will look for worlds to show on the world select screen. The original version of this argument, `-worldpath`, was removed because several game service providers have broken configurations that stop the server from running with an unhelpful error. This specific configuration was `-world` and `-worldpath`. In the new world, you can do the following:
* `-worldselectpath` should be used if you want to customize the server interactive boot world list (so that you can select from a number of worlds in non-standard locations).
* `-world` will behave as an absolute path to the world to load. This is the most common thing you want if you're starting the server and have a specific world in mind.
* `-worldselectpath` and `-worldname` should work together enabling you to select from a world from the list that you specify. This is *not* a world file name, but a world name as described by Terraria.
* `-worldselectpath` is identical to the old `-worldpath`. If you specify `-worldselectpath` and `-world` without specifying an absolute path the server will crash for sure.
* Thank you again to @fjfnaranjo for supplying a [detailed feature request](https://github.com/Pryaxis/TShock/issues/1914) explaining precisely why this option should be available. Without this, we would have had no context as to why this feature was useful or important. Thank you, @fjfnaranjo!
* This change was implemented by (@QuiCM, @hakusaro).
* Fixed kick on hardcore death / kick on mediumcore death / ban on either from taking action against journey mode players. (@hakusaro)
* Attempted to fix the problem with the magic mirror spawn problems. You should be able to remove your spawn point in SSC by right clicking on a bed now. (@hakusaro, @AxeelAnder)
* Added HandleFoodPlatterTryPlacing event, which is called whenever a player places a food in a plate. Add antihack to bouncer, to prevent removing food from plates if the region is protected; To prevent placement if they are not in range; To prevent placement if the item is not placed from player hand. (@Patrikkk)
* Fixed an offset error in NetTile that impacted `SendTileSquare`. It was being read as a `byte` and not a `ushort`. (@QuiCM)
* Removed packet monitoring from debug logs. To achieve the same results, install @QuiCM's packet monitor plugin (it does better things). (@hakusaro)
* Updated packet monitoring in send tile square handler for Bouncer debugging. (@hakusaro)
* Added `/sync`, activated with `tshock.synclocalarea`. This is a default guest permission. When the command is issued, the server will resync area around the player in the event of a desync issue. (@hakusaro)
* If your doors disappear, this command will allow a player to resync without having to disconnect from the server.
* The default group that gets this permission is `Guest` for the time being.
* To add this command to your guest group, give them `tshock.synclocalarea`, with `/group addperm guest tshock.synclocalarea`.
* This command may be removed at any time in the future (and will likely be removed when send tile square handling is fixed).
## TShock 4.4.0 (Pre-release 8)
* Update for OTAPI 2.0.0.36 and Terraria 1.4.0.4. (@hakusaro, @Patrikkk, @DeathCradle)

View file

@ -67,6 +67,7 @@ namespace TShockAPI
GetDataHandlers.MassWireOperation += OnMassWireOperation;
GetDataHandlers.PlayerDamage += OnPlayerDamage;
GetDataHandlers.KillMe += OnKillMe;
GetDataHandlers.FoodPlatterTryPlacing += OnFoodPlatterTryPlacing;
}
internal void OnGetSection(object sender, GetDataHandlers.GetSectionEventArgs args)
@ -557,6 +558,8 @@ namespace TShockAPI
return;
}
bool changed = false;
bool failed = false;
try
{
var tiles = new NetTile[size, size];
@ -568,7 +571,6 @@ namespace TShockAPI
}
}
bool changed = false;
for (int x = 0; x < size; x++)
{
int realx = tileX + x;
@ -708,9 +710,10 @@ namespace TShockAPI
catch
{
args.Player.SendTileSquare(tileX, tileY, size);
failed = true;
}
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare reimplemented from spaghetti from {0}", args.Player.Name);
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare from {0} {1} {2}", args.Player.Name, changed, failed);
args.Handled = true;
}
@ -1537,7 +1540,7 @@ namespace TShockAPI
if (npc.townNPC && npc.netID != NPCID.Guide && npc.netID != NPCID.Clothier)
{
if (type != BuffID.Lovestruck && type != BuffID.Stinky && type != BuffID.DryadsWard &&
type != BuffID.Wet && type != BuffID.Slimed)
type != BuffID.Wet && type != BuffID.Slimed && type != BuffID.GelBalloonBuff)
{
detectedNPCBuffTimeCheat = true;
}
@ -2062,6 +2065,54 @@ namespace TShockAPI
}
}
/// <summary>
/// Called when a player is trying to place an item into a food plate.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
internal void OnFoodPlatterTryPlacing(object sender, GetDataHandlers.FoodPlatterTryPlacingEventArgs args)
{
if (args.Player.ItemInHand.type != args.ItemID)
{
TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected item not placed by hand from {0}", args.Player.Name);
args.Player.SendTileSquare(args.TileX, args.TileY, 1);
args.Handled = true;
return;
}
if (args.Player.IsBeingDisabled())
{
TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected disabled from {0}", args.Player.Name);
Item item = new Item();
item.netDefaults(args.ItemID);
args.Player.GiveItemCheck(args.ItemID, item.Name, args.Stack, args.Prefix);
args.Player.SendTileSquare(args.TileX, args.TileY, 1);
args.Handled = true;
return;
}
if (!args.Player.HasBuildPermission(args.TileX, args.TileY))
{
TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected permissions from {0}", args.Player.Name);
Item item = new Item();
item.netDefaults(args.ItemID);
args.Player.GiveItemCheck(args.ItemID, item.Name, args.Stack, args.Prefix);
args.Player.SendTileSquare(args.TileX, args.TileY, 1);
args.Handled = true;
return;
}
if (!args.Player.IsInRange(args.TileX, args.TileY))
{
TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected range checks from {0}", args.Player.Name);
Item item = new Item();
item.netDefaults(args.ItemID);
args.Player.GiveItemCheck(args.ItemID, item.Name, args.Stack, args.Prefix);
args.Player.SendTileSquare(args.TileX, args.TileY, 1);
args.Handled = true;
return;
}
}
internal void OnSecondUpdate()
{
Task.Run(() =>

View file

@ -589,6 +589,10 @@ namespace TShockAPI
{
HelpText = "Creates a reference tables for Terraria data types and the TShock permission system in the server folder."
});
add(new Command(Permissions.synclocalarea, SyncLocalArea, "sync")
{
HelpText = "Sends all tiles from the server to the player to resync the client with the actual world state."
});
#endregion
add(new Command(Aliases, "aliases")
@ -5312,6 +5316,13 @@ namespace TShockAPI
return;
}
private static void SyncLocalArea(CommandArgs args)
{
args.Player.SendTileSquare((int) args.Player.TileX, (int) args.Player.TileY, 32);
args.Player.SendWarningMessage("Sync'd!");
return;
}
#endregion General Commands
#region Cheat Commands

View file

@ -64,7 +64,8 @@ namespace TShockAPI.DB
Permissions.canlogin,
Permissions.canpartychat,
Permissions.cantalkinthird,
Permissions.canchat));
Permissions.canchat,
Permissions.synclocalarea));
AddDefaultGroup("default", "guest",
string.Join(",",

View file

@ -150,7 +150,8 @@ namespace TShockAPI
{ PacketTypes.ToggleParty, HandleToggleParty },
{ PacketTypes.CrystalInvasionStart, HandleOldOnesArmy },
{ PacketTypes.PlayerHurtV2, HandlePlayerDamageV2 },
{ PacketTypes.PlayerDeathV2, HandlePlayerKillMeV2 }
{ PacketTypes.PlayerDeathV2, HandlePlayerKillMeV2 },
{ PacketTypes.FoodPlatterTryPlacing, HandleFoodPlatterTryPlacing }
};
}
@ -1863,6 +1864,52 @@ namespace TShockAPI
return args.Handled;
}
public class FoodPlatterTryPlacingEventArgs : GetDataHandledEventArgs
{
/// <summary>
/// The X tile position of the placement action.
/// </summary>
public short TileX { get; set; }
/// <summary>
/// The Y tile position of the placement action.
/// </summary>
public short TileY { get; set; }
/// <summary>
/// The Item ID that is being placed in the plate.
/// </summary>
public short ItemID { get; set; }
/// <summary>
/// The prefix of the item that is being placed in the plate.
/// </summary>
public byte Prefix { get; set; }
/// <summary>
/// The stack of the item that is being placed in the plate.
/// </summary>
public short Stack { get; set; }
}
/// <summary>
/// Called when a player is placing an item in a food plate.
/// </summary>
public static HandlerList<FoodPlatterTryPlacingEventArgs> FoodPlatterTryPlacing = new HandlerList<FoodPlatterTryPlacingEventArgs>();
private static bool OnFoodPlatterTryPlacing(TSPlayer player, MemoryStream data, short tileX, short tileY, short itemID, byte prefix, short stack)
{
if (FoodPlatterTryPlacing == null)
return false;
var args = new FoodPlatterTryPlacingEventArgs
{
Player = player,
Data = data,
TileX = tileX,
TileY = tileY,
ItemID = itemID,
Prefix = prefix,
Stack = stack,
};
FoodPlatterTryPlacing.Invoke(null, args);
return args.Handled;
}
#endregion
private static bool HandlePlayerInfo(GetDataHandlerArgs args)
@ -2118,7 +2165,7 @@ namespace TShockAPI
TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawn force teleport 'vanilla spawn' {0}", args.Player.Name);
}
if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0) && (args.TPlayer.SpawnX > 0) && ((args.TPlayer.SpawnX != args.Player.sX) && (args.TPlayer.SpawnY != args.Player.sY)))
else if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0) && (args.TPlayer.SpawnX > 0) && ((args.TPlayer.SpawnX != args.Player.sX) && (args.TPlayer.SpawnY != args.Player.sY)))
{
args.Player.sX = args.TPlayer.SpawnX;
@ -2269,6 +2316,14 @@ namespace TShockAPI
{
var player = args.Player;
var size = args.Data.ReadInt16();
var changeType = TileChangeType.None;
bool hasChangeType = ((size & 0x7FFF) & 0x8000) != 0;
if (hasChangeType)
{
changeType = (TileChangeType)args.Data.ReadInt8();
}
var tileX = args.Data.ReadInt16();
var tileY = args.Data.ReadInt16();
var data = args.Data;
@ -3524,7 +3579,7 @@ namespace TShockAPI
}
// Handle kicks/bans on mediumcore/hardcore deaths.
if (args.TPlayer.difficulty != 0) // Player is not softcore
if (args.TPlayer.difficulty == 1 || args.TPlayer.difficulty == 2) // Player is not softcore
{
bool mediumcore = args.TPlayer.difficulty == 1;
bool shouldBan = mediumcore ? TShock.Config.BanOnMediumcoreDeath : TShock.Config.BanOnHardcoreDeath;
@ -3559,7 +3614,19 @@ namespace TShockAPI
return false;
}
private static bool HandleFoodPlatterTryPlacing(GetDataHandlerArgs args)
{
short tileX = args.Data.ReadInt16();
short tileY = args.Data.ReadInt16();
short itemID = args.Data.ReadInt16();
byte prefix = args.Data.ReadInt8();
short stack = args.Data.ReadInt16();
if (OnFoodPlatterTryPlacing(args.Player, args.Data, tileX, tileY, itemID, prefix, stack))
return true;
return false;
}
public enum EditAction
{

View file

@ -30,7 +30,7 @@ namespace TShockAPI.Net
public short FrameX { get; set; }
public short FrameY { get; set; }
public bool Lighted { get; set; }
public byte Wall { get; set; }
public ushort Wall { get; set; }
public byte Liquid { get; set; }
public byte LiquidType { get; set; }
public bool Wire { get; set; }
@ -175,7 +175,7 @@ namespace TShockAPI.Net
}
if (HasWall)
stream.WriteInt8(Wall);
stream.WriteInt16((short)Wall);;
if (HasLiquid)
{
@ -218,7 +218,7 @@ namespace TShockAPI.Net
if (flags[2])
{
Wall = stream.ReadInt8();
Wall = stream.ReadUInt16();
}
if (flags[3])

View file

@ -465,6 +465,9 @@ namespace TShockAPI
[Description("Player can see advanced information about any user account.")]
public static readonly string advaccountinfo = "tshock.accountinfo.details";
[Description("Player can resync themselves with server state.")]
public static readonly string synclocalarea = "tshock.synclocalarea";
#endregion
/// <summary>
/// Lists all commands associated with a given permission

View file

@ -685,7 +685,7 @@ namespace TShockAPI
/// <returns>True if they can paint.</returns>
public bool HasPaintPermission(int x, int y)
{
return HasBuildPermission(x, y) || HasPermission(Permissions.canpaint);
return HasBuildPermission(x, y) && HasPermission(Permissions.canpaint);
}
/// <summary>Checks if a player can place ice, and if they can, tracks ice placements and removals.</summary>

View file

@ -1493,8 +1493,6 @@ namespace TShockAPI
PacketTypes type = e.MsgID;
Log.ConsoleDebug("Recv: {0:X}: {2} ({1:XX})", e.Msg.whoAmI, (byte)type, type);
var player = Players[e.Msg.whoAmI];
if (player == null || !player.ConnectionAlive)
{

View file

@ -221,4 +221,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>