Merge branch 'Pryaxis:general-devel' into general-devel

This commit is contained in:
shell 2022-01-03 20:03:19 +06:00 committed by GitHub
commit add6c4cbee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 271 additions and 7 deletions

View file

@ -105,6 +105,7 @@ namespace TShockAPI
GetDataHandlers.NPCAddBuff += OnNPCAddBuff;
GetDataHandlers.NPCHome += OnUpdateNPCHome;
GetDataHandlers.HealOtherPlayer += OnHealOtherPlayer;
GetDataHandlers.ReleaseNPC += OnReleaseNPC;
GetDataHandlers.PlaceObject += OnPlaceObject;
GetDataHandlers.PlaceTileEntity += OnPlaceTileEntity;
GetDataHandlers.PlaceItemFrame += OnPlaceItemFrame;
@ -1829,6 +1830,52 @@ namespace TShockAPI
return;
}
/// <summary>
/// A bouncer for checking NPC released by player
/// </summary>
/// <param name="sender">The object that triggered the event.</param>
/// <param name="args">The packet arguments that the event has.</param>
internal void OnReleaseNPC(object sender, GetDataHandlers.ReleaseNpcEventArgs args)
{
int x = args.X;
int y = args.Y;
short type = args.Type;
byte style = args.Style;
// if npc released outside allowed tile
if (x >= Main.maxTilesX * 16 - 16 || x < 0 || y >= Main.maxTilesY * 16 - 16 || y < 0)
{
TShock.Log.ConsoleDebug("Bouncer / OnReleaseNPC rejected out of bounds from {0}", args.Player.Name);
args.Handled = true;
return;
}
// if player disabled
if (args.Player.IsBeingDisabled())
{
TShock.Log.ConsoleDebug("Bouncer / OnReleaseNPC rejected npc release from {0}", args.Player.Name);
args.Handled = true;
return;
}
// if released npc not from its item (from crafted packet)
// e.g. using bunny item to release golden bunny
if (args.Player.TPlayer.lastVisualizedSelectedItem.makeNPC != type && args.Player.TPlayer.lastVisualizedSelectedItem.placeStyle != style)
{
TShock.Log.ConsoleDebug("Bouncer / OnReleaseNPC released different critter from {0}", args.Player.Name);
args.Player.Kick("Released critter was not from its item.", true);
args.Handled = true;
return;
}
if (args.Player.IsBouncerThrottled())
{
TShock.Log.ConsoleDebug("Bouncer / OnReleaseNPC rejected throttle from {0}", args.Player.Name);
args.Handled = true;
return;
}
}
/// <summary>Bouncer's PlaceObject hook reverts malicious tile placement.</summary>
/// <param name="sender">The object that triggered the event.</param>
/// <param name="args">The packet arguments that the event has.</param>
@ -2249,8 +2296,10 @@ namespace TShockAPI
*
* If the player was not specified, that is, the player index is -1, then it is definitely a custom cause, as you can only deal damage with a projectile or another player.
* This is how everything else works. If an NPC is specified, its value is not -1, which is a custom cause.
*
* Checking whether this damage came from the player is necessary, because the damage from the player can come even when it is hit by a NPC
*/
if (TShock.Config.Settings.DisableCustomDeathMessages &&
if (TShock.Config.Settings.DisableCustomDeathMessages && id != args.Player.Index &&
(reason._sourcePlayerIndex == -1 || reason._sourceNPCIndex != -1 || reason._sourceOtherIndex != -1 || reason._sourceCustomReason != null))
{
TShock.Log.ConsoleDebug("Bouncer / OnPlayerDamage rejected custom death message from {0}", args.Player.Name);

View file

@ -122,6 +122,7 @@ namespace TShockAPI
{ PacketTypes.PlayerAnimation, HandlePlayerAnimation },
{ PacketTypes.PlayerMana, HandlePlayerMana },
{ PacketTypes.PlayerTeam, HandlePlayerTeam },
{ PacketTypes.SignRead, HandleSignRead },
{ PacketTypes.SignNew, HandleSign },
{ PacketTypes.LiquidSet, HandleLiquidSet },
{ PacketTypes.PlayerBuff, HandlePlayerBuffList },
@ -135,6 +136,7 @@ namespace TShockAPI
{ PacketTypes.Teleport, HandleTeleport },
{ PacketTypes.PlayerHealOther, HandleHealOther },
{ PacketTypes.CatchNPC, HandleCatchNpc },
{ PacketTypes.ReleaseNPC, HandleReleaseNpc },
{ PacketTypes.TeleportationPotion, HandleTeleportationPotion },
{ PacketTypes.CompleteAnglerQuest, HandleCompleteAnglerQuest },
{ PacketTypes.NumberOfAnglerQuestsCompleted, HandleNumberOfAnglerQuestsCompleted },
@ -1187,6 +1189,43 @@ namespace TShockAPI
return args.Handled;
}
/// <summary>
/// For use in a SignRead event
/// </summary>
public class SignReadEventArgs : GetDataHandledEventArgs
{
/// <summary>
/// X location of the sign
/// </summary>
public int X { get; set; }
/// <summary>
/// Y location of the sign
/// </summary>
public int Y { get; set; }
}
/// <summary>
/// Sign - Called when a sign is read
/// </summary>
public static HandlerList<SignReadEventArgs> SignRead = new HandlerList<SignReadEventArgs>();
private static bool OnSignRead(TSPlayer player, MemoryStream data, int x, int y)
{
if (SignRead == null)
return false;
var args = new SignReadEventArgs
{
Player = player,
Data = data,
X = x,
Y = y,
};
SignRead.Invoke(null, args);
return args.Handled;
}
/// <summary>
/// For use in a Sign event
/// </summary>
@ -1638,6 +1677,56 @@ namespace TShockAPI
return args.Handled;
}
/// <summary>
/// The ReleaseNPC event arguments
/// </summary>
public class ReleaseNpcEventArgs : GetDataHandledEventArgs
{
/// <summary>
/// The X value of where NPC released
/// </summary>
public int X { get; set; }
/// <summary>
/// The Y value of where NPC released
/// </summary>
public int Y { get; set; }
/// <summary>
/// The NPC Type that player release
/// </summary>
public short Type { get; set; }
/// <summary>
/// The NPC release style
/// </summary>
public byte Style { get; set; }
}
/// <summary>
/// Called when player release a NPC, for checking critter released from item.
/// </summary>
public static HandlerList<ReleaseNpcEventArgs> ReleaseNPC = new HandlerList<ReleaseNpcEventArgs>();
private static bool OnReleaseNpc(TSPlayer player, MemoryStream data, int _x, int _y, short _type, byte _style)
{
if (ReleaseNPC == null)
{
return false;
}
var args = new ReleaseNpcEventArgs
{
Player = player,
Data = data,
X = _x,
Y = _y,
Type = _type,
Style = _style
};
ReleaseNPC.Invoke(null, args);
return args.Handled;
}
/// <summary>The arguments to the PlaceObject hook.</summary>
public class PlaceObjectEventArgs : GetDataHandledEventArgs
{
@ -3160,9 +3249,16 @@ namespace TShockAPI
TShock.Log.ConsoleDebug("Bouncer / HandleNpcTalk rejected from bouncer throttle from {0}", args.Player.Name);
return true;
}
// -1 is a magic value, represents not talking to an NPC
if (npc < -1 || npc >= Main.maxNPCs)
{
TShock.Log.ConsoleDebug("Bouncer / HandleNpcTalk rejected from bouncer out of bounds from {0}", args.Player.Name);
return true;
}
return false;
}
}
private static bool HandlePlayerAnimation(GetDataHandlerArgs args)
{
if (OnPlayerAnimation(args.Player, args.Data))
@ -3217,6 +3313,23 @@ namespace TShockAPI
return false;
}
private static bool HandleSignRead(GetDataHandlerArgs args)
{
var x = args.Data.ReadInt16();
var y = args.Data.ReadInt16();
if (OnSignRead(args.Player, args.Data, x, y))
return true;
if (x < 0 || y < 0 || x >= Main.maxTilesX || y >= Main.maxTilesY)
{
TShock.Log.ConsoleDebug("GetDataHandlers / HandleSignRead rejected out of bounds {0}", args.Player.Name);
return true;
}
return false;
}
private static bool HandleSign(GetDataHandlerArgs args)
{
var id = args.Data.ReadInt16();
@ -3487,6 +3600,11 @@ namespace TShockAPI
return true;
}
bool hasPaintSprayerAbilities(Item item) =>
item != null
&& item.stack > 0
&& (item.type == ItemID.PaintSprayer || item.type == ItemID.ArchitectGizmoPack);
// Not selecting paintbrush or paint scraper or the spectre versions? Hacking.
if (args.Player.SelectedItem.type != ItemID.PaintRoller &&
args.Player.SelectedItem.type != ItemID.PaintScraper &&
@ -3494,8 +3612,8 @@ namespace TShockAPI
args.Player.SelectedItem.type != ItemID.SpectrePaintRoller &&
args.Player.SelectedItem.type != ItemID.SpectrePaintScraper &&
args.Player.SelectedItem.type != ItemID.SpectrePaintbrush &&
!args.Player.Accessories.Any(i => i != null && i.stack > 0 &&
(i.type == ItemID.PaintSprayer || i.type == ItemID.ArchitectGizmoPack)))
!args.Player.Accessories.Any(hasPaintSprayerAbilities) &&
!args.Player.Inventory.Any(hasPaintSprayerAbilities))
{
TShock.Log.ConsoleDebug("GetDataHandlers / HandlePaintTile rejected select consistency {0}", args.Player.Name);
args.Player.SendData(PacketTypes.PaintTile, "", x, y, Main.tile[x, y].color());
@ -3658,10 +3776,31 @@ namespace TShockAPI
NetMessage.SendData((int)PacketTypes.NpcUpdate, -1, -1, NetworkText.Empty, npcID);
return true;
}
if(args.Player.IsBeingDisabled())
{
TShock.Log.ConsoleDebug("GetDataHandlers / HandleCatchNpc rejected catch npc {0}", args.Player.Name);
return true;
}
return false;
}
private static bool HandleReleaseNpc(GetDataHandlerArgs args)
{
var x = args.Data.ReadInt32();
var y = args.Data.ReadInt32();
var type = args.Data.ReadInt16();
var style = args.Data.ReadInt8();
if (OnReleaseNpc(args.Player, args.Data, x, y, type, style))
{
return true;
}
return false;
}
private static bool HandleTeleportationPotion(GetDataHandlerArgs args)
{
var type = args.Data.ReadByte();

View file

@ -53,5 +53,5 @@ using System.Runtime.InteropServices;
// 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)
[assembly: AssemblyVersion("4.5.11")]
[assembly: AssemblyFileVersion("4.5.11")]
[assembly: AssemblyVersion("4.5.12")]
[assembly: AssemblyFileVersion("4.5.12")]

View file

@ -898,6 +898,18 @@ namespace TShockAPI
}
}
/// <summary>
/// Gets the player's inventory (first 5 rows)
/// </summary>
public IEnumerable<Item> Inventory
{
get
{
for (int i = 0; i < 50; i++)
yield return TPlayer.inventory[i];
}
}
/// <summary>
/// Gets the player's accessories.
/// </summary>