Doors are still broken, however item frames work
This commit is contained in:
parent
d4a0f47e45
commit
e10e9f76f3
1 changed files with 162 additions and 18 deletions
|
|
@ -5,6 +5,8 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Terraria;
|
using Terraria;
|
||||||
|
using Terraria.DataStructures;
|
||||||
|
using Terraria.GameContent.Tile_Entities;
|
||||||
using Terraria.ID;
|
using Terraria.ID;
|
||||||
using Terraria.ObjectData;
|
using Terraria.ObjectData;
|
||||||
using TShockAPI.Net;
|
using TShockAPI.Net;
|
||||||
|
|
@ -26,6 +28,18 @@ namespace TShockAPI.Handlers
|
||||||
ItemID.FairyBoots
|
ItemID.FairyBoots
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Dictionary<int, int> _tileEntityIdToTileIdMap = new Dictionary<int, int>
|
||||||
|
{
|
||||||
|
{ TileID.TargetDummy, TETrainingDummy._myEntityID },
|
||||||
|
{ TileID.ItemFrame, TEItemFrame._myEntityID },
|
||||||
|
{ TileID.LogicSensor, TELogicSensor._myEntityID },
|
||||||
|
{ TileID.DisplayDoll, TEDisplayDoll._myEntityID },
|
||||||
|
{ TileID.WeaponsRack2, TEWeaponsRack._myEntityID },
|
||||||
|
{ TileID.HatRack, TEHatRack._myEntityID },
|
||||||
|
{ TileID.FoodPlatter, TEFoodPlatter._myEntityID },
|
||||||
|
{ TileID.TeleportationPylon, TETeleportationPylon._myEntityID }
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates a single tile
|
/// Updates a single tile
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -89,6 +103,8 @@ namespace TShockAPI.Handlers
|
||||||
}
|
}
|
||||||
|
|
||||||
tile.slope(slope);
|
tile.slope(slope);
|
||||||
|
|
||||||
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare updated a tile from type {0} to {1}", tile.type, newTile.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -97,30 +113,65 @@ namespace TShockAPI.Handlers
|
||||||
/// <param name="realx"></param>
|
/// <param name="realx"></param>
|
||||||
/// <param name="realy"></param>
|
/// <param name="realy"></param>
|
||||||
/// <param name="newTile"></param>
|
/// <param name="newTile"></param>
|
||||||
/// <param name="player"></param>
|
/// <param name="args"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal bool HandleFlowerBoots(int realx, int realy, NetTile newTile, TSPlayer player)
|
internal void HandleFlowerBoots(int realx, int realy, NetTile newTile, GetDataHandlers.SendTileSquareEventArgs args)
|
||||||
{
|
{
|
||||||
// We need to get the tile below the tile square to determine what grass types are allowed
|
// We need to get the tile below the tile square to determine what grass types are allowed
|
||||||
if (!WorldGen.InWorld(realx, realy + 1))
|
if (!WorldGen.InWorld(realx, realy + 1))
|
||||||
{
|
{
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITile tile = Main.tile[realx, realy + 1];
|
ITile tile = Main.tile[realx, realy + 1];
|
||||||
if (!_grassToPlantMap.TryGetValue(tile.type, out List<ushort> plantTiles) && !plantTiles.Contains(newTile.Type))
|
if (!_grassToPlantMap.TryGetValue(tile.type, out List<ushort> plantTiles) && !plantTiles.Contains(newTile.Type))
|
||||||
{
|
{
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
UpdateTile(Main.tile[realx, realy], newTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tile"></param>
|
||||||
|
/// <param name="newTile"></param>
|
||||||
|
internal void HandleConversionSpreads(ITile tile, NetTile newTile)
|
||||||
|
{
|
||||||
|
// Update if the existing tile or wall is convertible and the new tile or wall is a valid conversion
|
||||||
|
if (
|
||||||
|
((TileID.Sets.Conversion.Stone[tile.type] || Main.tileMoss[tile.type]) && (TileID.Sets.Conversion.Stone[newTile.Type] || Main.tileMoss[newTile.Type])) ||
|
||||||
|
((tile.type == 0 || tile.type == 59) && (newTile.Type == 0 || newTile.Type == 59)) ||
|
||||||
|
TileID.Sets.Conversion.Grass[tile.type] && TileID.Sets.Conversion.Grass[newTile.Type] ||
|
||||||
|
TileID.Sets.Conversion.Ice[tile.type] && TileID.Sets.Conversion.Ice[newTile.Type] ||
|
||||||
|
TileID.Sets.Conversion.Sand[tile.type] && TileID.Sets.Conversion.Sand[newTile.Type] ||
|
||||||
|
TileID.Sets.Conversion.Sandstone[tile.type] && TileID.Sets.Conversion.Sandstone[newTile.Type] ||
|
||||||
|
TileID.Sets.Conversion.HardenedSand[tile.type] && TileID.Sets.Conversion.HardenedSand[newTile.Type] ||
|
||||||
|
TileID.Sets.Conversion.Thorn[tile.type] && TileID.Sets.Conversion.Thorn[newTile.Type] ||
|
||||||
|
TileID.Sets.Conversion.Moss[tile.type] && TileID.Sets.Conversion.Moss[newTile.Type] ||
|
||||||
|
TileID.Sets.Conversion.MossBrick[tile.type] && TileID.Sets.Conversion.MossBrick[newTile.Type] ||
|
||||||
|
WallID.Sets.Conversion.Stone[tile.wall] && WallID.Sets.Conversion.Stone[newTile.Wall] ||
|
||||||
|
WallID.Sets.Conversion.Grass[tile.wall] && WallID.Sets.Conversion.Grass[newTile.Wall] ||
|
||||||
|
WallID.Sets.Conversion.Sandstone[tile.wall] && WallID.Sets.Conversion.Sandstone[newTile.Wall] ||
|
||||||
|
WallID.Sets.Conversion.HardenedSand[tile.wall] && WallID.Sets.Conversion.HardenedSand[newTile.Wall] ||
|
||||||
|
WallID.Sets.Conversion.PureSand[tile.wall] && WallID.Sets.Conversion.PureSand[newTile.Wall] ||
|
||||||
|
WallID.Sets.Conversion.NewWall1[tile.wall] && WallID.Sets.Conversion.NewWall1[newTile.Wall] ||
|
||||||
|
WallID.Sets.Conversion.NewWall2[tile.wall] && WallID.Sets.Conversion.NewWall2[newTile.Wall] ||
|
||||||
|
WallID.Sets.Conversion.NewWall3[tile.wall] && WallID.Sets.Conversion.NewWall3[newTile.Wall] ||
|
||||||
|
WallID.Sets.Conversion.NewWall4[tile.wall] && WallID.Sets.Conversion.NewWall4[newTile.Wall]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare processing a conversion update - [{0}|{1}] -> [{2}|{3}]", tile.type, tile.wall, newTile.Type, newTile.Wall);
|
||||||
|
UpdateTile(tile, newTile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ProcessSingleTile(int realx, int realy, NetTile newTile, int squareSize, GetDataHandlers.SendTileSquareEventArgs args)
|
internal void ProcessSingleTile(int realx, int realy, NetTile newTile, int squareSize, GetDataHandlers.SendTileSquareEventArgs args)
|
||||||
{
|
{
|
||||||
if (squareSize == 1 && args.Player.Accessories.Any(a => a != null && _flowerBootItems.Contains(a.type)))
|
if (squareSize == 1 && args.Player.Accessories.Any(a => a != null && _flowerBootItems.Contains(a.type)))
|
||||||
{
|
{
|
||||||
args.Handled = HandleFlowerBoots(realx, realy, newTile, args.Player);
|
HandleFlowerBoots(realx, realy, newTile, args);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,19 +187,86 @@ namespace TShockAPI.Handlers
|
||||||
UpdateTile(tile, newTile);
|
UpdateTile(tile, newTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HandleConversionSpreads(Main.tile[realx, realy], newTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="tileType"></param>
|
||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
/// <param name="newTiles"></param>
|
/// <param name="newTiles"></param>
|
||||||
/// <param name="realx"></param>
|
/// <param name="realx"></param>
|
||||||
/// <param name="realy"></param>
|
/// <param name="realy"></param>
|
||||||
/// <param name="player"></param>
|
/// <param name="args"></param>
|
||||||
public void ProcessTileObject(TileObjectData data, NetTile[,] newTiles, int realx, int realy, TSPlayer player)
|
public void ProcessTileObject(int tileType, TileObjectData data, NetTile[,] newTiles, int realx, int realy, GetDataHandlers.SendTileSquareEventArgs args)
|
||||||
{
|
{
|
||||||
|
// As long as the player has permission to build, we should allow a tile object to be placed
|
||||||
|
// More in depth checks should take place in handlers for the Place Object (79), Update Tile Entity (86), and Place Tile Entity (87) packets
|
||||||
|
if (!args.Player.HasBuildPermissionForTileObject(realx, realy, data.Width, data.Height))
|
||||||
|
{
|
||||||
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from no permission for tile object from {0}", args.Player.Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tileType == TileID.ClosedDoor || tileType == TileID.OpenDoor)
|
||||||
|
{
|
||||||
|
ProcessDoor(realx, realy, newTiles, args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < data.Width; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < data.Height; y++)
|
||||||
|
{
|
||||||
|
// Update all tiles in the tile object
|
||||||
|
UpdateTile(Main.tile[realx + x, realy + y], newTiles[x, y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Handled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessDoor(int realx, int realy, NetTile[,] newTiles, GetDataHandlers.SendTileSquareEventArgs args)
|
||||||
|
{
|
||||||
|
//If we handle this then doors disappear... We only send back the tile square if args.Handled == true, so somewhere we're either breaking or not implementing the tile square properly
|
||||||
|
///Calling UpdateTile on all tiles in newTiles doesn't help either.
|
||||||
|
//Need to figure out what's differing from Vanilla in this regard
|
||||||
|
args.Handled = false;
|
||||||
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare processing door from {0}", args.Player.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<char> symbols = new List<char> { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y' };
|
||||||
|
void VisualiseTileSquare(NetTile[,] tiles, int size)
|
||||||
|
{
|
||||||
|
Dictionary<int, char> tileToCharMap = new Dictionary<int, char>();
|
||||||
|
int lastCharIndex = 0;
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder("\n");
|
||||||
|
|
||||||
|
for (int y = 0; y < size; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < size; x++)
|
||||||
|
{
|
||||||
|
NetTile tile = tiles[x, y];
|
||||||
|
char symbol;
|
||||||
|
if (tileToCharMap.ContainsKey(tile.Type))
|
||||||
|
{
|
||||||
|
symbol = tileToCharMap[tile.Type];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
symbol = symbols[lastCharIndex++];
|
||||||
|
tileToCharMap.Add(tile.Type, symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append(symbol);
|
||||||
|
}
|
||||||
|
sb.Append("\n");
|
||||||
|
}
|
||||||
|
sb.Append("Key: " + String.Join(", ", tileToCharMap.Select(kvp => $"{kvp.Value} = {kvp.Key}")));
|
||||||
|
|
||||||
|
TShock.Log.ConsoleDebug(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -162,6 +280,9 @@ namespace TShockAPI.Handlers
|
||||||
int tileX = args.TileX;
|
int tileX = args.TileX;
|
||||||
int tileY = args.TileY;
|
int tileY = args.TileY;
|
||||||
|
|
||||||
|
// By default, we'll handle everything
|
||||||
|
args.Handled = true;
|
||||||
|
|
||||||
if (args.Player.HasPermission(Permissions.allowclientsideworldedit))
|
if (args.Player.HasPermission(Permissions.allowclientsideworldedit))
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare accepted clientside world edit from {0}", args.Player.Name);
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare accepted clientside world edit from {0}", args.Player.Name);
|
||||||
|
|
@ -174,7 +295,6 @@ namespace TShockAPI.Handlers
|
||||||
if (size > 5)
|
if (size > 5)
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from non-vanilla tilemod from {0}", args.Player.Name);
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from non-vanilla tilemod from {0}", args.Player.Name);
|
||||||
args.Handled = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,7 +302,6 @@ namespace TShockAPI.Handlers
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from throttle from {0}", args.Player.Name);
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from throttle from {0}", args.Player.Name);
|
||||||
args.Player.SendTileSquare(tileX, tileY, size);
|
args.Player.SendTileSquare(tileX, tileY, size);
|
||||||
args.Handled = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,7 +309,6 @@ namespace TShockAPI.Handlers
|
||||||
{
|
{
|
||||||
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from being disabled from {0}", args.Player.Name);
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from being disabled from {0}", args.Player.Name);
|
||||||
args.Player.SendTileSquare(tileX, tileY, size);
|
args.Player.SendTileSquare(tileX, tileY, size);
|
||||||
args.Handled = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,13 +322,18 @@ namespace TShockAPI.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VisualiseTileSquare(tiles, size);
|
||||||
|
|
||||||
for (int x = 0; x < size; x++)
|
for (int x = 0; x < size; x++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < size; y++)
|
for (int y = 0; y < size; y++)
|
||||||
{
|
{
|
||||||
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare tile ({0}, {1})", x, y);
|
||||||
|
|
||||||
// Do not handle already processed tiles
|
// Do not handle already processed tiles
|
||||||
if (processed[x, y])
|
if (processed[x, y])
|
||||||
{
|
{
|
||||||
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare skipping processed tile from {0}", args.Player.Name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,7 +341,7 @@ namespace TShockAPI.Handlers
|
||||||
int realy = tileY + y;
|
int realy = tileY + y;
|
||||||
|
|
||||||
if ((realx < 0 || realx >= Main.maxTilesX)
|
if ((realx < 0 || realx >= Main.maxTilesX)
|
||||||
|| (realy < 0 || realy < Main.maxTilesY))
|
|| (realy < 0 || realy > Main.maxTilesY))
|
||||||
{
|
{
|
||||||
processed[x, y] = true;
|
processed[x, y] = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -245,17 +368,38 @@ namespace TShockAPI.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessTileObject(data, newTiles, realx, realy, args.Player);
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare processing tile object ({1}) from {0}", args.Player.Name, newTile.Type);
|
||||||
|
ProcessTileObject(newTile.Type, data, newTiles, realx, realy, args);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Main.tile[realx, realy].type == TileID.ClosedDoor || Main.tile[realx, realy].type == TileID.OpenDoor)
|
||||||
|
{
|
||||||
|
NetTile[,] newTiles = new NetTile[2, 3];
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
newTiles[i, j] = tiles[x + i, y + j];
|
||||||
|
processed[x + i, y + j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessDoor(realx, realy, newTiles, args);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare processing single tile ({1}->{2}) from {0}", args.Player.Name, Main.tile[realx, realy].type, newTile.Type);
|
||||||
ProcessSingleTile(realx, realy, newTile, size, args);
|
ProcessSingleTile(realx, realy, newTile, size, args);
|
||||||
processed[x, y] = true;
|
processed[x, y] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.Handled == true)
|
||||||
|
{
|
||||||
|
args.Player.SendTileSquare(tileX, tileY, size);
|
||||||
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare reimplemented from spaghetti from {0}", args.Player.Name);
|
TShock.Log.ConsoleDebug("Bouncer / SendTileSquare reimplemented from spaghetti from {0}", args.Player.Name);
|
||||||
args.Handled = true;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue