Merge pull request #545 from NyxStudios/1.2_terraria

Update to Terraria Protocol 1.2
This commit is contained in:
Lucas Nicodemus 2013-09-30 21:04:41 -07:00
commit 33e0627f9e
19 changed files with 994 additions and 674 deletions

View file

@ -24,7 +24,6 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using TShockAPI.PluginUpdater;
using Terraria;
using TShockAPI.DB;
@ -186,7 +185,9 @@ namespace TShockAPI
add(Permissions.causeevents, Star, "star");
add(Permissions.causeevents, Fullmoon, "fullmoon");
add(Permissions.causeevents, Bloodmoon, "bloodmoon");
add(Permissions.causeevents, Eclipse, "eclipse");
add(Permissions.causeevents, Invade, "invade");
add(Permissions.causeevents, Rain, "rain");
add(Permissions.spawnboss, Eater, "eater");
add(Permissions.spawnboss, Eye, "eye");
add(Permissions.spawnboss, King, "king");
@ -483,7 +484,7 @@ namespace TShockAPI
if (TShock.RememberedPos.GetLeavePos(args.Player.Name, args.Player.IP) != Vector2.Zero)
{
Vector2 pos = TShock.RememberedPos.GetLeavePos(args.Player.Name, args.Player.IP);
args.Player.Teleport((int)pos.X, (int)pos.Y + 3);
args.Player.Teleport((int)pos.X*16, (int)pos.Y *16 + 48);
}
args.Player.LoginHarassed = false;
@ -1259,7 +1260,6 @@ namespace TShockAPI
{
args.Player.SendInfoMessage("Starting plugin update process:");
args.Player.SendInfoMessage("This may take a while, do not turn off the server!");
new PluginUpdaterThread(args.Player);
}
private static void ManageRest(CommandArgs args)
@ -1354,6 +1354,12 @@ namespace TShockAPI
TShock.Utils.Broadcast(string.Format("{0} turned on the blood moon.", args.Player.Name), Color.Green);
}
private static void Eclipse(CommandArgs args)
{
TSPlayer.Server.SetEclipse(true);
TShock.Utils.Broadcast(string.Format("{0} has forced an Eclipse!", args.Player.Name), Color.Green);
}
private static void Invade(CommandArgs args)
{
if (Main.invasionSize <= 0)
@ -1635,7 +1641,7 @@ namespace TShockAPI
private static void Spawn(CommandArgs args)
{
if (args.Player.Teleport(Main.spawnTileX, Main.spawnTileY))
if (args.Player.Teleport(Main.spawnTileX*16, Main.spawnTileY*16))
args.Player.SendSuccessMessage("Teleported to the map's spawnpoint.");
}
@ -1643,33 +1649,53 @@ namespace TShockAPI
{
if (args.Parameters.Count < 1)
{
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /tp <player> ");
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /tp <player>");
args.Player.SendErrorMessage(" /tp <x> <y>");
return;
}
string plStr = String.Join(" ", args.Parameters);
var players = TShock.Utils.FindPlayer(plStr);
if (players.Count == 0)
args.Player.SendErrorMessage("Invalid player!");
else if (players.Count > 1)
TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name));
else if (!players[0].TPAllow && !args.Player.Group.HasPermission(Permissions.tpall))
if(args.Parameters.Count == 2)
{
var plr = players[0];
args.Player.SendErrorMessage(plr.Name + " has prevented users from teleporting to them.");
plr.SendInfoMessage(args.Player.Name + " attempted to teleport to you.");
float x, y;
if (float.TryParse(args.Parameters[0], out x) && float.TryParse(args.Parameters[1], out y))
{
args.Player.Teleport(x, y);
args.Player.SendSuccessMessage("Teleported!");
}
}
else
{
var plr = players[0];
if (args.Player.Teleport(plr.TileX, plr.TileY + 3))
string plStr = String.Join(" ", args.Parameters);
var players = TShock.Utils.FindPlayer(plStr);
if (players.Count == 0)
{
args.Player.SendSuccessMessage(string.Format("Teleported to {0}.", plr.Name));
if (!args.Player.Group.HasPermission(Permissions.tphide))
plr.SendInfoMessage(args.Player.Name + " teleported to you.");
args.Player.SendErrorMessage("Invalid user name.");
args.Player.SendErrorMessage("Proper syntax: /tp <player>");
args.Player.SendErrorMessage(" /tp <x> <y>");
}
else if (players.Count > 1)
TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name));
else if (!players[0].TPAllow && !args.Player.Group.HasPermission(Permissions.tpall))
{
var plr = players[0];
args.Player.SendErrorMessage(plr.Name + " has prevented users from teleporting to them.");
plr.SendInfoMessage(args.Player.Name + " attempted to teleport to you.");
}
else
{
var plr = players[0];
if (args.Player.Teleport(plr.TileX * 16, plr.TileY * 16 + 48))
{
args.Player.SendSuccessMessage(string.Format("Teleported to {0}.", plr.Name));
if (!args.Player.Group.HasPermission(Permissions.tphide))
plr.SendInfoMessage(args.Player.Name + " teleported to you.");
}
}
}
}
}
private static void TPHere(CommandArgs args)
{
@ -1688,7 +1714,7 @@ namespace TShockAPI
{
if (Main.player[i].active && (Main.player[i] != args.TPlayer))
{
if (TShock.Players[i].Teleport(args.Player.TileX, args.Player.TileY + 3))
if (TShock.Players[i].Teleport(args.Player.TileX*16, args.Player.TileY*16 + 48))
TShock.Players[i].SendSuccessMessage(string.Format("You were teleported to {0}.", args.Player.Name) + ".");
}
}
@ -1707,7 +1733,7 @@ namespace TShockAPI
else
{
var plr = players[0];
if (plr.Teleport(args.Player.TileX, args.Player.TileY + 3))
if (plr.Teleport(args.Player.TileX*16, args.Player.TileY*16 + 48))
{
plr.SendInfoMessage(string.Format("You were teleported to {0}.", args.Player.Name));
args.Player.SendSuccessMessage(string.Format("You brought {0} here.", plr.Name));
@ -1851,7 +1877,7 @@ namespace TShockAPI
var plr = foundplr[0];
if (warp.WarpPos != Vector2.Zero)
{
if (plr.Teleport((int)warp.WarpPos.X, (int)warp.WarpPos.Y + 3))
if (plr.Teleport((int)warp.WarpPos.X*16, (int)warp.WarpPos.Y*16 + 48))
{
plr.SendSuccessMessage(string.Format("{0} warped you to {1}.", args.Player.Name, warpName));
args.Player.SendSuccessMessage(string.Format("You warped {0} to {1}.", plr.Name, warpName));
@ -1869,7 +1895,7 @@ namespace TShockAPI
var warp = TShock.Warps.FindWarp(warpName);
if (warp.WarpPos != Vector2.Zero)
{
if (args.Player.Teleport((int)warp.WarpPos.X, (int)warp.WarpPos.Y + 3))
if (args.Player.Teleport((int)warp.WarpPos.X*16, (int)warp.WarpPos.Y*16 + 48))
args.Player.SendSuccessMessage("Warped to " + warpName + ".");
}
else
@ -2484,7 +2510,27 @@ namespace TShockAPI
}
}
//TODO: Come back here
private static void Rain(CommandArgs args)
{
if (args.Parameters.Count != 1)
{
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /rain <stop/start>");
return;
}
switch (args.Parameters[0])
{
case "start":
Main.StartRain();
TSPlayer.All.SendInfoMessage(string.Format("{0} caused it to rain.", args.Player.Name));
break;
case "stop":
Main.StopRain();
TSPlayer.All.SendInfoMessage(string.Format("{0} ended the downpour.", args.Player.Name));
break;
}
}
private static void Slap(CommandArgs args)
{
@ -2900,13 +2946,13 @@ namespace TShockAPI
// worth the effort as chances are very low that overwriting the wire for a few
// nanoseconds will cause much trouble.
Tile tile = Main.tile[boundaryPoint.X, boundaryPoint.Y];
bool oldWireState = tile.wire;
tile.wire = true;
bool oldWireState = tile.wire();
tile.wire(true);
try {
args.Player.SendTileSquare(boundaryPoint.X, boundaryPoint.Y, 1);
} finally {
tile.wire = oldWireState;
tile.wire(oldWireState);
}
}
}
@ -3027,7 +3073,7 @@ namespace TShockAPI
break;
}
args.Player.Teleport(region.Area.Center.X, region.Area.Center.Y + 3);
args.Player.Teleport(region.Area.Center.X*16, region.Area.Center.Y*16 + 48);
break;
}
@ -3703,12 +3749,7 @@ namespace TShockAPI
playerToHeal = args.Player;
}
Item heart = TShock.Utils.GetItemById(58);
Item star = TShock.Utils.GetItemById(184);
for (int i = 0; i < 20; i++)
playerToHeal.GiveItem(heart.type, heart.name, heart.width, heart.height, heart.maxStack);
for (int i = 0; i < 10; i++)
playerToHeal.GiveItem(star.type, star.name, star.width, star.height, star.maxStack);
playerToHeal.Heal();
if (playerToHeal == args.Player)
{
args.Player.SendSuccessMessage("You just got healed!");
@ -3829,7 +3870,7 @@ namespace TShockAPI
case "tree":
for (int i = x - 1; i < x + 2; i++)
{
Main.tile[i, y].active = true;
Main.tile[i, y].active(true);
Main.tile[i, y].type = 2;
Main.tile[i, y].wall = 0;
}
@ -3840,20 +3881,20 @@ namespace TShockAPI
case "epictree":
for (int i = x - 1; i < x + 2; i++)
{
Main.tile[i, y].active = true;
Main.tile[i, y].active(true);
Main.tile[i, y].type = 2;
Main.tile[i, y].wall = 0;
}
Main.tile[x, y - 1].wall = 0;
Main.tile[x, y - 1].liquid = 0;
Main.tile[x, y - 1].active = true;
Main.tile[x, y - 1].active(true);
WorldGen.GrowEpicTree(x, y);
name = "Epic Tree";
break;
case "mushroom":
for (int i = x - 1; i < x + 2; i++)
{
Main.tile[i, y].active = true;
Main.tile[i, y].active(true);
Main.tile[i, y].type = 70;
Main.tile[i, y].wall = 0;
}
@ -3867,7 +3908,7 @@ namespace TShockAPI
name = "Cactus";
break;
case "herb":
Main.tile[x, y].active = true;
Main.tile[x, y].active(true);
Main.tile[x, y].frameX = 36;
Main.tile[x, y].type = 83;
WorldGen.GrowAlch(x, y);

View file

@ -124,7 +124,7 @@ namespace TShockAPI.DB
{
try
{
return database.Query("INSERT INTO Bans (IP, Name, Reason, BanningUser, Date, Expiration) VALUES (@0, @1, @2, @3, @4, @5);", ip, name, reason, banner, DateTime.Now.ToString("G"), expiration) != 0;
return database.Query("INSERT INTO Bans (IP, Name, Reason, BanningUser, Date, Expiration) VALUES (@0, @1, @2, @3, @4, @5);", ip, name, reason, banner, DateTime.UtcNow.ToString("s"), expiration) != 0;
}
catch (Exception ex)
{

View file

@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.CodeDom.Compiler;
using System.Data;
using System.Collections.Generic;
using System.Linq;
@ -38,6 +39,7 @@ namespace TShockAPI.DB
new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true},
new SqlColumn("Password", MySqlDbType.VarChar, 128),
new SqlColumn("Usergroup", MySqlDbType.Text),
new SqlColumn("Registered", MySqlDbType.Text),
new SqlColumn("LastAccessed", MySqlDbType.Text),
new SqlColumn("KnownIPs", MySqlDbType.Text)
);
@ -60,8 +62,8 @@ namespace TShockAPI.DB
int ret;
try
{
ret = database.Query("INSERT INTO Users (Username, Password, UserGroup) VALUES (@0, @1, @2);", user.Name,
TShock.Utils.HashPassword(user.Password), user.Group);
ret = database.Query("INSERT INTO Users (Username, Password, UserGroup, Registered) VALUES (@0, @1, @2, @3);", user.Name,
TShock.Utils.HashPassword(user.Password), user.Group, DateTime.UtcNow.ToString("s"));
}
catch (Exception ex)
{
@ -146,7 +148,7 @@ namespace TShockAPI.DB
{
try
{
if (database.Query("UPDATE Users SET LastAccessed = @0, KnownIps = @1 WHERE Username = @2;", DateTime.Now.ToString("G"), user.KnownIps, user.Name) == 0)
if (database.Query("UPDATE Users SET LastAccessed = @0, KnownIps = @1 WHERE Username = @2;", DateTime.UtcNow.ToString("s"), user.KnownIps, user.Name) == 0)
throw new UserNotExistException(user.Name);
}
catch (Exception ex)
@ -268,6 +270,7 @@ namespace TShockAPI.DB
user.Group = result.Get<string>("Usergroup");
user.Password = result.Get<string>("Password");
user.Name = result.Get<string>("Username");
user.Registered = result.Get<string>("Registered");
user.LastAccessed = result.Get<string>("LastAccessed");
user.KnownIps = result.Get<string>("KnownIps");
return user;
@ -280,14 +283,16 @@ namespace TShockAPI.DB
public string Name { get; set; }
public string Password { get; set; }
public string Group { get; set; }
public string Registered { get; set; }
public string LastAccessed { get; set; }
public string KnownIps { get; set; }
public User(string name, string pass, string group, string last, string known)
public User(string name, string pass, string group, string registered, string last, string known)
{
Name = name;
Password = pass;
Group = group;
Registered = registered;
LastAccessed = last;
KnownIps = known;
}
@ -297,6 +302,7 @@ namespace TShockAPI.DB
Name = "";
Password = "";
Group = "";
Registered = "";
LastAccessed = "";
KnownIps = "";
}

View file

@ -78,17 +78,17 @@ namespace TShockAPI
/// <summary>
/// The Tile ID being edited.
/// </summary>
public byte Type { get; set; }
public byte EditData { get; set; }
/// <summary>
/// The EditType.
/// (KillTile = 0, PlaceTile = 1, KillWall = 2, PlaceWall = 3, KillTileNoItem = 4, PlaceWire = 5, KillWire = 6)
/// </summary>
public byte EditType { get; set; }
public EditAction Action { get; set; }
/// <summary>
/// Did the tile get destroyed successfully.
/// </summary>
public bool Fail { get; set; }
public EditType editDetail { get; set; }
/// <summary>
/// Used when a tile is placed to denote a subtype of tile. (e.g. for tile id 21: Chest = 0, Gold Chest = 1)
@ -100,7 +100,7 @@ namespace TShockAPI
/// TileEdit - called when a tile is placed or destroyed
/// </summary>
public static HandlerList<TileEditEventArgs> TileEdit;
private static bool OnTileEdit(TSPlayer ply, int x, int y, byte type, byte editType, bool fail, byte style)
private static bool OnTileEdit(TSPlayer ply, int x, int y, EditAction action, EditType editDetail, byte editData, byte style)
{
if (TileEdit == null)
return false;
@ -110,9 +110,9 @@ namespace TShockAPI
Player = ply,
X = x,
Y = y,
Type = type,
EditType = editType,
Fail = fail,
Action = action,
EditData = editData,
editDetail = editDetail,
Style = style
};
TileEdit.Invoke(null, args);
@ -443,13 +443,15 @@ namespace TShockAPI
/// Velocity of the player
/// </summary>
public Vector2 Velocity { get; set; }
public byte Pulley { get; set; }
}
/// <summary>
/// PlayerUpdate - When the player sends it's updated information to the server
/// </summary>
public static HandlerList<PlayerUpdateEventArgs> PlayerUpdate;
private static bool OnPlayerUpdate(byte player, byte control, byte item, Vector2 position, Vector2 velocity)
private static bool OnPlayerUpdate(byte player, byte control, byte item, Vector2 position, Vector2 velocity, byte pulley)
{
if (PlayerUpdate == null)
return false;
@ -461,16 +463,17 @@ namespace TShockAPI
Item = item,
Position = position,
Velocity = velocity,
Pulley = pulley
};
PlayerUpdate.Invoke(null, args);
return args.Handled;
}
public static bool TSCheckNoclip(Vector2 Position, int Width, int Height)
{
int num = (int)(Position.X / 16f) - 1;
int num2 = (int)((Position.X + (float)Width) / 16f) + 2;
int num3 = (int)(Position.Y / 16f) - 1;
int num4 = (int)((Position.Y + (float)Height) / 16f) + 2;
int num = (int)(Position.X / 16f);
int num2 = (int)((Position.X + (float)Width) / 16f);
int num3 = (int)(Position.Y / 16f);
int num4 = (int)((Position.Y + (float)Height) / 16f);
if (num < 0)
{
num = 0;
@ -499,15 +502,17 @@ namespace TShockAPI
{
for (int j = num3; j < num4; j++)
{
if (Main.tile[i, j] != null && Main.tile[i, j].active && Main.tileSolid[(int)Main.tile[i, j].type] && !Main.tileSolidTop[(int)Main.tile[i, j].type] &&(((int)Main.tile[i,j].type !=53) && ((int)Main.tile[i,j].type !=112) && ((int)Main.tile[i,j].type !=116) && ((int)Main.tile[i,j].type !=123)) && !Main.tile[i,j].lava)
if (Main.tile[i, j] == null || !Main.tile[i, j].active() || !Main.tileSolid[(int) Main.tile[i, j].type] || Main.tileSolidTop[(int) Main.tile[i, j].type] || (((int) Main.tile[i, j].type == 53) || ((int) Main.tile[i, j].type == 112) || ((int) Main.tile[i, j].type == 116) || ((int) Main.tile[i, j].type == 123)) || Main.tile[i, j].lava() || ((Main.tile[i, j].tileHeader2 & 16) == 16) || ((Main.tile[i, j].tileHeader2 & 32) == 32) || ((Main.tile[i, j].tileHeader & 32) == 32) || Main.tile[i, j].honey() || !Main.tileSolid[(int) Main.tile[i + 1, j].type] || !Main.tileSolid[(int) Main.tile[i - 1, j].type] || !Main.tileSolid[(int) Main.tile[i, j + 1].type] || !Main.tileSolid[(int) Main.tile[i, j - 1].type] || !Main.tileSolid[(int) Main.tile[i - 1, j - 1].type] || !Main.tileSolid[(int) Main.tile[i - 1, j + 1].type] || !Main.tileSolid[(int) Main.tile[i + 1, j - 1].type] || !Main.tileSolid[(int) Main.tile[i + 1, j + 1].type] || Main.tileSand[(int) Main.tile[i, j].type])
{
Vector2 vector;
vector.X = (float)(i * 16);
vector.Y = (float)(j * 16);
if (Position.X + (float)Width > vector.X && Position.X < vector.X + 16f && Position.Y + (float)Height > vector.Y && Position.Y < vector.Y + 16f)
{
return true;
}
continue;
}
Vector2 vector;
vector.X = (float) (i*16);
vector.Y = (float) (j*16);
if (Position.X + (float) Width > vector.X && Position.X < vector.X + 16f && Position.Y + (float) Height > vector.Y && Position.Y < vector.Y + 16f)
{
return true;
}
}
}
@ -628,20 +633,20 @@ namespace TShockAPI
/// </summary>
public int TileY { get; set; }
/// <summary>
/// ???
/// Amount of liquid
/// </summary>
public byte Liquid { get; set;}
public byte Amount { get; set;}
/// <summary>
/// True if lava
/// Type of Liquid: 0=water, 1=lave, 2=honey
/// </summary>
public bool Lava { get; set; }
public byte Type { get; set; }
}
/// <summary>
/// LiquidSet - When ever a liquid is set
/// </summary>
public static HandlerList<LiquidSetEventArgs> LiquidSet;
private static bool OnLiquidSet(int tilex, int tiley, byte liquid, bool lava)
private static bool OnLiquidSet(int tilex, int tiley, byte amount, byte type)
{
if (LiquidSet == null)
return false;
@ -650,8 +655,8 @@ namespace TShockAPI
{
TileX = tilex,
TileY = tiley,
Liquid = liquid,
Lava = lava,
Amount = amount,
Type = type,
};
LiquidSet.Invoke(null, args);
return args.Handled;
@ -919,6 +924,10 @@ namespace TShockAPI
/// </summary>
public byte Prefix { get; set; }
/// <summary>
/// No Delay on pickup
/// </summary>
public bool NoDelay { get; set; }
/// <summary>
/// Item type
/// </summary>
public short Type { get; set; }
@ -928,7 +937,7 @@ namespace TShockAPI
/// </summary>
public static HandlerList<ItemDropEventArgs> ItemDrop;
private static bool OnItemDrop(short id, Vector2 pos, Vector2 vel, byte stacks, byte prefix, short type)
private static bool OnItemDrop(short id, Vector2 pos, Vector2 vel, byte stacks, byte prefix, bool noDelay, short type)
{
if (ItemDrop == null)
return false;
@ -940,6 +949,7 @@ namespace TShockAPI
Velocity = vel,
Stacks = stacks,
Prefix = prefix,
NoDelay = noDelay,
Type = type,
};
ItemDrop.Invoke(null, args);
@ -1125,6 +1135,53 @@ namespace TShockAPI
return args.Handled;
}
/// <summary>
/// For use with a NPCStrike event
/// </summary>
public class TeleportEventArgs : HandledEventArgs
{
/// <summary>
/// ???
/// </summary>
public Int16 ID { get; set; }
/// <summary>
/// Flag is a bit field
/// if the first bit is set -> 0 = player, 1 = NPC
/// if the second bit is set, ignore this packet
/// if the third bit is set, style +1
/// if the fourth bit is set, style +1
/// </summary>
public byte Flag { get; set; }
/// <summary>
/// X Location
/// </summary>
public float X { get; set; }
/// <summary>
/// Y Location
/// </summary>
public float Y { get; set; }
}
/// <summary>
/// NPCStrike - Called when an NPC is attacked
/// </summary>
public static HandlerList<TeleportEventArgs> Teleport;
private static bool OnTeleport(Int16 id, byte f, float x, float y)
{
if (Teleport == null)
return false;
var args = new TeleportEventArgs
{
ID = id,
Flag = f,
X = x,
Y = y
};
Teleport.Invoke(null, args);
return args.Handled;
}
#endregion
public static void InitGetDataHandler()
{
@ -1169,7 +1226,10 @@ namespace TShockAPI
{PacketTypes.PasswordSend, HandlePassword},
{PacketTypes.ContinueConnecting2, HandleConnecting},
{PacketTypes.ProjectileDestroy, HandleProjectileKill},
{PacketTypes.SpawnBossorInvasion, HandleSpawnBoss}
{PacketTypes.SpawnBossorInvasion, HandleSpawnBoss},
{PacketTypes.Teleport, HandleTeleport},
{PacketTypes.PaintTile, HandlePaintTile},
{PacketTypes.PaintWall, HandlePaintWall}
};
}
@ -1251,7 +1311,7 @@ namespace TShockAPI
if (args.Player.FirstMaxHP == 0)
args.Player.FirstMaxHP = max;
if (max > TShock.Config.MaxHealth && max > args.Player.FirstMaxHP)
if ((max > TShock.Config.MaxHealth && max > args.Player.FirstMaxHP) && !args.Player.Group.HasPermission(Permissions.ignorestathackdetection))
{
TShock.Utils.ForceKick(args.Player, "Hacked Client Detected.", true);
return false;
@ -1262,6 +1322,11 @@ namespace TShockAPI
args.Player.PlayerData.maxHealth = max;
}
if (args.Player.Group.HasPermission(Permissions.godmode) && (cur < max))
{
args.Player.Heal(args.TPlayer.statLifeMax);
}
return false;
}
@ -1330,6 +1395,7 @@ namespace TShockAPI
private static bool HandleConnecting(GetDataHandlerArgs args)
{
var user = TShock.Users.GetUserByName(args.Player.Name);
if (user != null && !TShock.Config.DisableLoginBeforeJoin)
{
args.Player.RequiresPassword = true;
@ -1388,7 +1454,7 @@ namespace TShockAPI
return true;
}
}
args.Player.LoginFailsBySsi = false;
args.Player.LoginFailsBySsi = false;
if (group.HasPermission(Permissions.ignorestackhackdetection))
args.Player.IgnoreActionsForCheating = "none";
@ -1543,10 +1609,10 @@ namespace TShockAPI
continue;
}
// Server now has a range check built in
/*if (TShock.CheckRangePermission(args.Player, realx, realy))
if (TShock.CheckRangePermission(args.Player, realx, realy))
{
continue;
}*/
}
if ((tile.type == 128 && newtile.Type == 128) || (tile.type == 105 && newtile.Type == 105) || (tile.type == 139 && newtile.Type == 139))
{
if (TShock.Config.EnableInsecureTileFixes)
@ -1673,16 +1739,39 @@ namespace TShockAPI
return true;
}
public enum EditAction
{
KillTile = 0,
PlaceTile,
KillWall,
PlaceWall,
KillTileNoItem,
PlaceWire,
KillWire,
PoundTile
}
public enum EditType
{
Fail = 0,
Type,
Slope,
}
private static bool HandleTile(GetDataHandlerArgs args)
{
var type = args.Data.ReadInt8();
EditAction action = (EditAction)args.Data.ReadInt8();
var tileX = args.Data.ReadInt32();
var tileY = args.Data.ReadInt32();
var tiletype = args.Data.ReadInt8();
var fail = tiletype == 1;
var editData = args.Data.ReadInt8();
EditType type = (action == EditAction.KillTile || action == EditAction.KillWall ||
action == EditAction.KillTileNoItem)
? EditType.Fail
: (action == EditAction.PlaceTile || action == EditAction.PlaceWall)
? EditType.Type
: EditType.Slope;
var style = args.Data.ReadInt8();
if (OnTileEdit(args.Player, tileX, tileY, tiletype, type, fail, style))
if (OnTileEdit(args.Player, tileX, tileY, action, type, editData, style))
return true;
if (!TShock.Utils.TilePlacementValid(tileX, tileY))
return false;
@ -1767,62 +1856,64 @@ namespace TShockAPI
if (type == 0 && Main.tile[tileX, tileY].type != 127 && !Main.tileCut[Main.tile[tileX, tileY].type] && !rightClickKill.Contains(Main.tile[tileX, tileY].type))
{
// If the tile is an axe tile and they aren't selecting an axe, they're hacking.
if (Main.tileAxe[Main.tile[tileX, tileY].type] && selectedItem.axe == 0)
if (Main.tileAxe[Main.tile[tileX, tileY].type] && (selectedItem.axe == 0 && selectedItem.explosive == 0 && args.Player.RecentFuse == 0))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
}
// If the tile is a hammer tile and they aren't selecting an hammer, they're hacking.
else if (Main.tileHammer[Main.tile[tileX, tileY].type] && selectedItem.hammer == 0)
else if (Main.tileHammer[Main.tile[tileX, tileY].type] && (selectedItem.hammer == 0 && selectedItem.explosive == 0 && args.Player.RecentFuse == 0))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
}
// If the tile is a pickaxe tile and they aren't selecting an pickaxe, they're hacking.
else if ((!Main.tileAxe[Main.tile[tileX, tileY].type] && !Main.tileHammer[Main.tile[tileX, tileY].type]) && selectedItem.pick == 0)
else if ((!Main.tileAxe[Main.tile[tileX, tileY].type] && !Main.tileHammer[Main.tile[tileX, tileY].type]) && (selectedItem.pick == 0 && selectedItem.explosive == 0 && args.Player.RecentFuse == 0))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
}
}
else if (type == 2)
else if (action == EditAction.KillWall)
{
// If they aren't selecting an hammer, they're hacking.
if (selectedItem.hammer == 0)
if (selectedItem.hammer == 0 && selectedItem.explosive == 0 && args.Player.RecentFuse == 0)
{
args.Player.SendTileSquare(tileX, tileY);
return true;
}
}
else if (type == 1 || type == 3)
else if (action == EditAction.PlaceTile || action == EditAction.PlaceWall)
{
if (type == 1 && TShock.Config.PreventInvalidPlaceStyle && ((tiletype == 4 && style > 8) ||
(tiletype == 13 && style > 4) || (tiletype == 15 && style > 1) || (tiletype == 21 && style > 6) ||
(tiletype == 82 && style > 5) || (tiletype == 91 && style > 3) || (tiletype == 105 && style > 42) ||
(tiletype == 135 && style > 3) || (tiletype == 139 && style > 12) || (tiletype == 144 && style > 2) ||
(tiletype == 149 && style > 2)))
if (action == EditAction.PlaceTile && TShock.Config.PreventInvalidPlaceStyle && ((editData == 4 && style > 11) ||
(editData == 13 && style > 4) || (editData == 15 && style > 17) || (editData == 21 && style > 22) ||
(editData == 82 && style > 5) || (editData == 91 && style > 21) || (editData == 105 && style > 49) ||
(editData == 135 && style > 6) || (editData == 139 && style > 27) || (editData == 144 && style > 2) ||
(editData == 149 && style > 2)))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
}
// If they aren't selecting the item which creates the tile or wall, they're hacking.
if (tiletype != 127 && tiletype != (type == 1 ? selectedItem.createTile : selectedItem.createWall))
if (editData != 127 && editData != (action == EditAction.PlaceTile ? selectedItem.createTile : selectedItem.createWall))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
}
if (TShock.Itembans.ItemIsBanned(selectedItem.name, args.Player) || tiletype >= (type == 1 ? Main.maxTileSets : Main.maxWallTypes))
if (TShock.Itembans.ItemIsBanned(selectedItem.name, args.Player) || editData >= (action == EditAction.PlaceTile ? Main.maxTileSets : Main.maxWallTypes))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
}
if (type == 1 && (tiletype == 29 || tiletype == 97) && TShock.Config.ServerSideInventory && TShock.Config.DisablePiggybanksOnSSI)
if (action == EditAction.PlaceTile && (editData == 29 || editData == 97) && TShock.Config.ServerSideInventory && TShock.Config.DisablePiggybanksOnSSI)
{
args.Player.SendMessage("You cannot place this tile because server side inventory is enabled.", Color.Red);
args.Player.SendTileSquare(tileX, tileY);
return true;
}
if (type == 1 && tiletype == 21)
if (action == EditAction.PlaceTile && editData == 21)
{
if (TShock.Utils.MaxChests())
{
@ -1838,7 +1929,7 @@ namespace TShockAPI
}
}
}
else if (type == 5)
else if (action == EditAction.PlaceWire)
{
// If they aren't selecting the wrench, they're hacking.
if (args.TPlayer.inventory[args.TPlayer.selectedItem].type != 509)
@ -1847,7 +1938,7 @@ namespace TShockAPI
return true;
}
}
else if (type == 6)
else if (action == EditAction.KillWire)
{
// If they aren't selecting the wire cutter, they're hacking.
if (args.TPlayer.inventory[args.TPlayer.selectedItem].type != 510)
@ -1863,13 +1954,13 @@ namespace TShockAPI
return true;
}
if (TShock.CheckTilePermission(args.Player, tileX, tileY, tiletype, type))
if (TShock.CheckTilePermission(args.Player, tileX, tileY, editData, action))
{
args.Player.SendTileSquare(tileX, tileY);
return true;
}
if ((tiletype == 127 || Main.tileCut[tiletype]) && (type == 0 || type == 4))
if ((editData == 127 || Main.tileCut[editData]) && (action ==EditAction.KillTile || action == EditAction.KillTileNoItem))
{
return false;
}
@ -1900,26 +1991,103 @@ namespace TShockAPI
return true;
}
if ( ( type == 1 || type == 3 ) && !args.Player.Group.HasPermission(Permissions.ignoreplacetiledetection))
if ( ( action == EditAction.PlaceTile || action == EditAction.PlaceWall ) && !args.Player.Group.HasPermission(Permissions.ignoreplacetiledetection))
{
args.Player.TilePlaceThreshold++;
var coords = new Vector2(tileX, tileY);
if (!args.Player.TilesCreated.ContainsKey(coords))
args.Player.TilesCreated.Add(coords, Main.tile[tileX, tileY].Data);
args.Player.TilesCreated.Add(coords, Main.tile[tileX, tileY]);
}
if ((type == 0 || type == 4 || type == 2) && Main.tileSolid[Main.tile[tileX, tileY].type] &&
if ((action == EditAction.KillTile || action == EditAction.KillTileNoItem || action == EditAction.KillWall) && Main.tileSolid[Main.tile[tileX, tileY].type] &&
!args.Player.Group.HasPermission(Permissions.ignorekilltiledetection))
{
args.Player.TileKillThreshold++;
var coords = new Vector2(tileX, tileY);
if (!args.Player.TilesDestroyed.ContainsKey(coords))
args.Player.TilesDestroyed.Add(coords, Main.tile[tileX, tileY].Data);
args.Player.TilesDestroyed.Add(coords, Main.tile[tileX, tileY]);
}
return false;
}
/// <summary>
/// For use with a PaintTile event
/// </summary>
public class PaintTileEventArgs : HandledEventArgs
{
/// <summary>
/// X Location
/// </summary>
public Int32 X { get; set; }
/// <summary>
/// Y Location
/// </summary>
public Int32 Y { get; set; }
/// <summary>
/// Type
/// </summary>
public byte type { get; set; }
}
/// <summary>
/// NPCStrike - Called when an NPC is attacked
/// </summary>
public static HandlerList<PaintTileEventArgs> PaintTile;
private static bool OnPaintTile(Int32 x, Int32 y, byte t)
{
if (PaintTile == null)
return false;
var args = new PaintTileEventArgs
{
X = x,
Y = y,
type = t
};
PaintTile.Invoke(null, args);
return args.Handled;
}
/// <summary>
/// For use with a PaintWall event
/// </summary>
public class PaintWallEventArgs : HandledEventArgs
{
/// <summary>
/// X Location
/// </summary>
public Int32 X { get; set; }
/// <summary>
/// Y Location
/// </summary>
public Int32 Y { get; set; }
/// <summary>
/// Type
/// </summary>
public byte type { get; set; }
}
/// <summary>
/// Called When a wall is painted
/// </summary>
public static HandlerList<PaintWallEventArgs> PaintWall;
private static bool OnPaintWall(Int32 x, Int32 y, byte t)
{
if (PaintWall == null)
return false;
var args = new PaintWallEventArgs
{
X = x,
Y = y,
type = t
};
PaintWall.Invoke(null, args);
return args.Handled;
}
private static bool HandleTogglePvp(GetDataHandlerArgs args)
{
byte id = args.Data.ReadInt8();
@ -1987,13 +2155,19 @@ namespace TShockAPI
var item = args.Data.ReadInt8();
var pos = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle());
var vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle());
if (OnPlayerUpdate(plr, control, item, pos, vel))
byte pulley = args.Data.ReadInt8();
if (OnPlayerUpdate(plr, control, item, pos, vel, pulley))
return true;
if (item < 0 || item >= args.TPlayer.inventory.Length)
{
return true;
}
if (pulley > 2)
{
return true;
}
if (args.Player.LastNetPosition == Vector2.Zero)
{
return true;
@ -2036,8 +2210,8 @@ namespace TShockAPI
args.Player.SendMessage("PvP is forced! Enable PvP or else you can't do anything!",
Color.Red);
}
int lastTileX = (int) (args.Player.LastNetPosition.X/16f);
int lastTileY = (int) (args.Player.LastNetPosition.Y/16f);
var lastTileX = args.Player.LastNetPosition.X;
var lastTileY = args.Player.LastNetPosition.Y;
if (!args.Player.Teleport(lastTileX, lastTileY))
{
args.Player.Spawn();
@ -2056,9 +2230,9 @@ namespace TShockAPI
TSCheckNoclip(pos, args.TPlayer.width, args.TPlayer.height) && !TShock.Config.IgnoreNoClip
&& !args.TPlayer.tongued)
{
int lastTileX = (int)(args.Player.LastNetPosition.X / 16f);
int lastTileY = (int)(args.Player.LastNetPosition.Y / 16f);
if (!args.Player.Teleport(lastTileX, lastTileY + 3))
var lastTileX = args.Player.LastNetPosition.X;
var lastTileY = args.Player.LastNetPosition.Y;
if (!args.Player.Teleport(lastTileX, lastTileY + 48))
{
args.Player.SendErrorMessage("You got stuck in a solid object, Sent to spawn point.");
args.Player.Spawn();
@ -2092,6 +2266,8 @@ namespace TShockAPI
args.TPlayer.controlRight = false;
args.TPlayer.controlJump = false;
args.TPlayer.controlUseItem = false;
args.TPlayer.pulley = pulley != 0;
args.TPlayer.pulleyDir = pulley;
args.TPlayer.direction = -1;
if ((control & 1) == 1)
{
@ -2207,12 +2383,14 @@ namespace TShockAPI
}
}
// force all explosives server-side.
// force all explosives server-side. -- DOES NOT WORK DUE TO LATENCY
if (hasPermission && (type == 28 || type == 29 || type == 37))
{
args.Player.RemoveProjectile(ident, owner);
Projectile.NewProjectile(pos.X, pos.Y, vel.X, vel.Y, type, dmg, knockback);
return true;
// Denotes that the player has recently set a fuse - used for cheat detection.
args.Player.RecentFuse = 10;
// args.Player.RemoveProjectile(ident, owner);
// Projectile.NewProjectile(pos.X, pos.Y, vel.X, vel.Y, type, dmg, knockback);
// return true;
}
return false;
@ -2291,11 +2469,12 @@ namespace TShockAPI
{
int tileX = args.Data.ReadInt32();
int tileY = args.Data.ReadInt32();
byte liquid = args.Data.ReadInt8();
bool lava = args.Data.ReadBoolean();
byte amount = args.Data.ReadInt8();
byte type = args.Data.ReadInt8();
if (OnLiquidSet(tileX, tileY, liquid, lava))
if (OnLiquidSet(tileX, tileY, amount, type))
return true;
if (tileX < 0 || tileX >= Main.maxTilesX || tileY < 0 || tileY >= Main.maxTilesY)
return false;
@ -2314,12 +2493,16 @@ namespace TShockAPI
if (!args.Player.Group.HasPermission(Permissions.ignoreliquidsetdetection))
{
args.Player.TileLiquidThreshold++;
args.Player.TileLiquidThreshold+=amount;
}
if (liquid != 0)
if (amount != 0)
{
int bucket = 0;
if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 206)
int bucket = -1;
if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 205)
{
bucket = 0;
}
else if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 206)
{
bucket = 1;
}
@ -2327,8 +2510,12 @@ namespace TShockAPI
{
bucket = 2;
}
else if (args.TPlayer.inventory[args.TPlayer.selectedItem].type == 1128)
{
bucket = 3;
}
if(lava && bucket != 2)
if (type == 1 && !(bucket == 2 || bucket == 0))
{
args.Player.SendErrorMessage("You do not have permission to perform this action.");
args.Player.Disable("Spreading lava without holding a lava bucket");
@ -2336,7 +2523,7 @@ namespace TShockAPI
return true;
}
if(lava && (!args.Player.Group.HasPermission(Permissions.usebanneditem) &&
if(type == 1 && (!args.Player.Group.HasPermission(Permissions.usebanneditem) &&
TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player)))
{
args.Player.SendErrorMessage("You do not have permission to perform this action.");
@ -2345,7 +2532,7 @@ namespace TShockAPI
return true;
}
if (!lava && bucket != 1)
if (type == 0 && !(bucket == 1 || bucket == 0))
{
args.Player.SendErrorMessage("You do not have permission to perform this action.");
args.Player.Disable("Spreading water without holding a water bucket");
@ -2353,7 +2540,7 @@ namespace TShockAPI
return true;
}
if (!lava && (!args.Player.Group.HasPermission(Permissions.usebanneditem) &&
if (type == 0 && (!args.Player.Group.HasPermission(Permissions.usebanneditem) &&
TShock.Itembans.ItemIsBanned("Water Bucket", args.Player)))
{
args.Player.SendErrorMessage("You do not have permission to perform this action.");
@ -2361,6 +2548,23 @@ namespace TShockAPI
args.Player.SendTileSquare(tileX, tileY);
return true;
}
if (type == 2 &&!(bucket == 3 || bucket == 0))
{
args.Player.SendErrorMessage("You do not have permission to perform this action.");
args.Player.Disable("Spreading honey without holding a honey bucket");
args.Player.SendTileSquare(tileX, tileY);
return true;
}
if (type == 2 && (!args.Player.Group.HasPermission(Permissions.usebanneditem) &&
TShock.Itembans.ItemIsBanned("Honey Bucket", args.Player)))
{
args.Player.SendErrorMessage("You do not have permission to perform this action.");
args.Player.Disable("Using banned honey bucket without permissions");
args.Player.SendTileSquare(tileX, tileY);
return true;
}
}
if (TShock.CheckTilePermission(args.Player, tileX, tileY))
@ -2631,13 +2835,14 @@ namespace TShockAPI
var vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle());
var stacks = args.Data.ReadInt8();
var prefix = args.Data.ReadInt8();
var noDelay = args.Data.ReadBoolean();
var type = args.Data.ReadInt16();
if (OnItemDrop(id, pos, vel, stacks, prefix, type))
if (OnItemDrop(id, pos, vel, stacks, prefix, noDelay, type))
return true;
// player is attempting to crash clients
if (type < -24 || type >= Main.maxItemTypes)
if (type < -48 || type >= Main.maxItemTypes)
{
return true;
}
@ -2737,6 +2942,11 @@ namespace TShockAPI
return true;
}
if (args.Player.Group.HasPermission(Permissions.godmode))
{
args.Player.Heal(args.TPlayer.statLifeMax);
}
return false;
}
@ -2939,5 +3149,96 @@ namespace TShockAPI
TShock.Utils.SendLogs(string.Format("{0} summoned {1}", args.Player.Name, boss), Color.PaleVioletRed, args.Player);
return false;
}
private static bool HandlePaintTile(GetDataHandlerArgs args)
{
var x = args.Data.ReadInt32();
var y = args.Data.ReadInt32();
var t = args.Data.ReadInt8();
if (OnPaintTile(x, y, t))
return true;
if (!args.Player.Group.HasPermission(Permissions.canpaint))
{
args.Player.SendTileSquare(x, y);
return true;
}
return false;
}
private static bool HandlePaintWall(GetDataHandlerArgs args)
{
var x = args.Data.ReadInt32();
var y = args.Data.ReadInt32();
var t = args.Data.ReadInt8();
if (OnPaintTile(x, y, t))
return true;
if (!args.Player.Group.HasPermission(Permissions.canpaint))
{
args.Player.SendTileSquare(x, y);
return true;
}
return false;
}
private static bool HandleTeleport(GetDataHandlerArgs args)
{
var flag = args.Data.ReadInt8();
var id = args.Data.ReadInt16();
var x = args.Data.ReadSingle();
var y = args.Data.ReadSingle();
if (OnTeleport(id, flag, x, y))
return true;
byte style = 0;
var isNPC = false;
if ((flag & 1) == 1)
{
isNPC = true;
}
if ((flag & 2) != 2)
{
if ((flag & 4) == 4)
{
style++;
}
if ((flag & 8) == 8)
{
style++;
}
if (id > (isNPC ? 200 : 255))
{
return true;
}
if (Main.player[id] == null || TShock.Players[id] == null)
{
return true;
}
if (!isNPC && !args.Player.Group.HasPermission(Permissions.tp))
{
args.Player.SendErrorMessage("You do not have permission to teleport.");
Main.player[id].Teleport(new Vector2(Main.player[id].position.X, Main.player[id].position.Y), style);
NetMessage.SendData(65, -1, -1, "", 0, (float)id, Main.player[id].position.X, Main.player[id].position.Y, style);
return true;
}
if (!isNPC)
{
TShock.Players[id].Teleport(x, y, style);
}
}
return true;
}
}
}

View file

@ -31,9 +31,13 @@ namespace TShockAPI.Net
public short FrameY { get; set; }
public byte Wall { get; set; }
public byte Liquid { get; set; }
public bool Lava { get; set; }
public byte LiquidType { get; set; }
public bool Wire { get; set; }
public byte HalfBrick { get; set; }
public byte Actuator { get; set; }
public bool Inactive { get; set; }
public bool IsHalf { get; set; }
public bool IsActuator { get; set; }
public bool HasWall
{
get { return Wall > 0; }
@ -57,8 +61,10 @@ namespace TShockAPI.Net
FrameY = -1;
Wall = 0;
Liquid = 0;
Lava = false;
Wire = false;
HalfBrick = 0;
Actuator = 0;
Inactive = false;
}
public NetTile(Stream stream)
@ -71,7 +77,7 @@ namespace TShockAPI.Net
{
var flags = TileFlags.None;
if (Active)
if ((Active) && (!Inactive))
flags |= TileFlags.Active;
if (HasWall)
@ -82,6 +88,17 @@ namespace TShockAPI.Net
if (Wire)
flags |= TileFlags.Wire;
if (IsHalf)
flags |= TileFlags.HalfBrick;
if (IsActuator)
flags |= TileFlags.Actuator;
if (Inactive)
{
flags |= TileFlags.Inactive;
}
stream.WriteInt8((byte) flags);
@ -101,7 +118,7 @@ namespace TShockAPI.Net
if (HasLiquid)
{
stream.WriteInt8(Liquid);
stream.WriteBoolean(Lava);
stream.WriteInt8(LiquidType);
}
}
@ -128,11 +145,23 @@ namespace TShockAPI.Net
if (flags.HasFlag(TileFlags.Liquid))
{
Liquid = stream.ReadInt8();
Lava = stream.ReadBoolean();
LiquidType = stream.ReadInt8();
}
if (flags.HasFlag(TileFlags.Wire))
Wire = true;
if (flags.HasFlag(TileFlags.HalfBrick))
IsHalf = true;
if (flags.HasFlag(TileFlags.Actuator))
IsActuator = true;
if (flags.HasFlag(TileFlags.Inactive))
{
Inactive = true;
Active = false;
}
}
}
@ -144,6 +173,9 @@ namespace TShockAPI.Net
Lighted = 2,
Wall = 4,
Liquid = 8,
Wire = 16
Wire = 16,
HalfBrick = 32,
Actuator = 64,
Inactive = 128
}
}
}

View file

@ -25,7 +25,7 @@ namespace TShockAPI.Net
{
public override PacketTypes ID
{
get { return PacketTypes.ProjectileNew; }
get{ return PacketTypes.ProjectileNew; }
}
public short Index { get; set; }

View file

@ -24,7 +24,7 @@ using System.Text;
namespace TShockAPI.Net
{
[Flags]
public enum WorldInfoFlag : byte
public enum BossFlags : byte
{
None = 0,
OrbSmashed = 1,
@ -35,12 +35,25 @@ namespace TShockAPI.Net
DownedClown = 32
}
[Flags]
public enum BossFlags2 : byte
{
None = 0,
DownedMechBoss1 = 1,
DownedMechBoss2 = 2,
DownedMechBoss3 = 4,
DownedMechBossAny = 8,
CloudBg = 16,
Crimson = 32
}
public class WorldInfoMsg : BaseMsg
{
public int Time { get; set; }
public bool DayTime { get; set; }
public byte MoonPhase { get; set; }
public bool BloodMoon { get; set; }
public bool Eclipse { get; set; }
public int MaxTilesX { get; set; }
public int MaxTilesY { get; set; }
public int SpawnX { get; set; }
@ -48,7 +61,37 @@ namespace TShockAPI.Net
public int WorldSurface { get; set; }
public int RockLayer { get; set; }
public int WorldID { get; set; }
public WorldInfoFlag WorldFlags { get; set; }
public byte MoonType { get; set; }
public int TreeX0 { get; set; }
public int TreeX1 { get; set; }
public int TreeX2 { get; set; }
public byte TreeStyle0 { get; set; }
public byte TreeStyle1 { get; set; }
public byte TreeStyle2 { get; set; }
public byte TreeStyle3 { get; set; }
public int CaveBackX0 { get; set; }
public int CaveBackX1 { get; set; }
public int CaveBackX2 { get; set; }
public byte CaveBackStyle0 { get; set; }
public byte CaveBackStyle1 { get; set; }
public byte CaveBackStyle2 { get; set; }
public byte CaveBackStyle3 { get; set; }
public byte SetBG0 { get; set; }
public byte SetBG1 { get; set; }
public byte SetBG2 { get; set; }
public byte SetBG3 { get; set; }
public byte SetBG4 { get; set; }
public byte SetBG5 { get; set; }
public byte SetBG6 { get; set; }
public byte SetBG7 { get; set; }
public byte IceBackStyle { get; set; }
public byte JungleBackStyle { get; set; }
public byte HellBackStyle { get; set; }
public float WindSpeed { get; set; }
public byte NumberOfClouds { get; set; }
public BossFlags BossFlags { get; set; }
public BossFlags2 BossFlags2 { get; set; }
public float Rain { get; set; }
public string WorldName { get; set; }
public override PacketTypes ID
@ -62,6 +105,7 @@ namespace TShockAPI.Net
stream.WriteBoolean(DayTime);
stream.WriteInt8(MoonPhase);
stream.WriteBoolean(BloodMoon);
stream.WriteBoolean(Eclipse);
stream.WriteInt32(MaxTilesX);
stream.WriteInt32(MaxTilesY);
stream.WriteInt32(SpawnX);
@ -69,7 +113,37 @@ namespace TShockAPI.Net
stream.WriteInt32(WorldSurface);
stream.WriteInt32(RockLayer);
stream.WriteInt32(WorldID);
stream.WriteInt8((byte) WorldFlags);
stream.WriteByte(MoonType);
stream.WriteInt32(TreeX0);
stream.WriteInt32(TreeX1);
stream.WriteInt32(TreeX2);
stream.WriteByte(TreeStyle0);
stream.WriteByte(TreeStyle1);
stream.WriteByte(TreeStyle2);
stream.WriteByte(TreeStyle3);
stream.WriteInt32(CaveBackX0);
stream.WriteInt32(CaveBackX1);
stream.WriteInt32(CaveBackX2);
stream.WriteByte(CaveBackStyle0);
stream.WriteByte(CaveBackStyle1);
stream.WriteByte(CaveBackStyle2);
stream.WriteByte(CaveBackStyle3);
stream.WriteByte(SetBG0);
stream.WriteByte(SetBG1);
stream.WriteByte(SetBG2);
stream.WriteByte(SetBG3);
stream.WriteByte(SetBG4);
stream.WriteByte(SetBG5);
stream.WriteByte(SetBG6);
stream.WriteByte(SetBG7);
stream.WriteByte(IceBackStyle);
stream.WriteByte(JungleBackStyle);
stream.WriteByte(HellBackStyle);
stream.WriteSingle(WindSpeed);
stream.WriteByte(NumberOfClouds);
stream.WriteInt8((byte) BossFlags);
stream.WriteInt8((byte)BossFlags2);
stream.WriteSingle(Rain);
stream.WriteBytes(Encoding.UTF8.GetBytes(WorldName));
}
}

View file

@ -22,8 +22,8 @@ using System.ComponentModel;
using System.IO;
using System.Net.Sockets;
using System.Text;
using Hooks;
using Terraria;
using TerrariaApi.Server;
namespace TShockAPI
{
@ -34,6 +34,8 @@ namespace TShockAPI
/// </summary>
public int BytesPerUpdate { get; set; }
private readonly TShock plugin;
private PacketBuffer[] buffers = new PacketBuffer[Netplay.serverSock.Length];
private int[] Bytes = new int[52];
@ -45,8 +47,9 @@ namespace TShockAPI
Command flush;
#endif
public PacketBufferer()
public PacketBufferer(TShock p)
{
plugin = p;
BytesPerUpdate = 0xFFFF;
for (int i = 0; i < buffers.Length; i++)
buffers[i] = new PacketBuffer();
@ -58,9 +61,9 @@ namespace TShockAPI
Commands.ChatCommands.Add(flush);
#endif
NetHooks.SendBytes += ServerHooks_SendBytes;
ServerHooks.SocketReset += ServerHooks_SocketReset;
GameHooks.PostUpdate += GameHooks_Update;
ServerApi.Hooks.NetSendBytes.Register(plugin, ServerHooks_SendBytes);
ServerApi.Hooks.ServerSocketReset.Register(plugin, ServerHooks_SocketReset);
ServerApi.Hooks.GamePostUpdate.Register(plugin, GameHooks_Update);
}
~PacketBufferer()
@ -82,9 +85,9 @@ namespace TShockAPI
Commands.ChatCommands.Remove(dump);
Commands.ChatCommands.Remove(flush);
#endif
NetHooks.SendBytes -= ServerHooks_SendBytes;
ServerHooks.SocketReset -= ServerHooks_SocketReset;
GameHooks.PostUpdate -= GameHooks_Update;
ServerApi.Hooks.NetSendBytes.Deregister(plugin, ServerHooks_SendBytes);
ServerApi.Hooks.ServerSocketReset.Deregister(plugin, ServerHooks_SocketReset);
ServerApi.Hooks.GamePostUpdate.Deregister(plugin, GameHooks_Update);
}
}
@ -107,7 +110,7 @@ namespace TShockAPI
Compressed = new int[52];
}
private void GameHooks_Update()
private void GameHooks_Update(EventArgs args)
{
FlushAll();
}
@ -148,9 +151,9 @@ namespace TShockAPI
}
private void ServerHooks_SocketReset(ServerSock socket)
private void ServerHooks_SocketReset(SocketResetEventArgs args)
{
buffers[socket.whoAmI] = new PacketBuffer();
buffers[args.Socket.whoAmI] = new PacketBuffer();
}
public bool SendBytes(ServerSock socket, byte[] buffer)
@ -217,10 +220,10 @@ namespace TShockAPI
return false;
}
private void ServerHooks_SendBytes(ServerSock socket, byte[] buffer, int offset, int count, HandledEventArgs e)
private void ServerHooks_SendBytes(SendBytesEventArgs args)
{
e.Handled = true;
BufferBytes(socket, buffer, offset, count);
args.Handled = true;
BufferBytes(args.Socket, args.Buffer, args.Offset, args.Count);
}
#if DEBUG_NET

View file

@ -247,6 +247,9 @@ namespace TShockAPI
[Description("User can modify the world.")]
public static readonly string canbuild = "tshock.world.modify";
[Description("User can paint tiles.")]
public static readonly string canpaint = "tshock.world.paint";
// Non-grouped
@ -280,6 +283,9 @@ namespace TShockAPI
[Description("User can get the server info.")]
public static readonly string serverinfo = "tshock.info";
[Description("Player recovers health as damage is taken. Can be one shotted.")]
public static readonly string godmode = "tshock.godmode";
/// <summary>
/// Lists all commands associated with a given permission
/// </summary>

View file

@ -1,87 +0,0 @@
/*
TShock, a server mod for Terraria
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.IO;
using System.Threading;
using Terraria;
namespace TShockAPI.PluginUpdater
{
class PluginUpdaterThread
{
private TSPlayer invoker;
public PluginUpdaterThread(TSPlayer player)
{
invoker = player;
PluginVersionCheck.PluginUpdate += PluginUpdate;
HandleUpdate();
}
private void HandleUpdate()
{
foreach(PluginContainer cont in ProgramServer.Plugins)
new Thread(PluginVersionCheck.CheckPlugin).Start(cont.Plugin);
}
private int Updates = 0;
private void PluginUpdate(UpdateArgs args)
{
Updates++;
if(args.Success && String.IsNullOrEmpty(args.Error))
{
invoker.SendSuccessMessage(String.Format("{0} was downloaded successfully.", args.Plugin.Name));
}
else if(args.Success)
{
invoker.SendSuccessMessage(String.Format("{0} was skipped. Reason: {1}", args.Plugin.Name, args.Error));
}
else
{
invoker.SendSuccessMessage(String.Format("{0} failed to downloaded. Error: {1}", args.Plugin.Name, args.Error));
}
if(Updates >= Terraria.ProgramServer.Plugins.Count)
{
PluginVersionCheck.PluginUpdate -= PluginUpdate;
invoker.SendSuccessMessage("All plugins have been downloaded. Now copying them to the plugin folder...");
string folder = Path.Combine(TShock.SavePath, "UpdatedPlugins");
string dest = Path.Combine(TShock.SavePath, "..", "ServerPlugins");
foreach (string dir in Directory.GetDirectories(folder, "*", System.IO.SearchOption.AllDirectories))
{
string new_folder = dest + dir.Substring(folder.Length);
if (!Directory.Exists(new_folder))
Directory.CreateDirectory(new_folder);
}
foreach (string file_name in Directory.GetFiles(folder, "*.*", System.IO.SearchOption.AllDirectories))
{
TSPlayer.Server.SendSuccessMessage(String.Format("Copied {0}", file_name));
File.Copy(file_name, dest + file_name.Substring(folder.Length), true);
}
Directory.Delete(folder, true);
invoker.SendSuccessMessage("All plugins have been processed. Restart the server to have access to the new plugins.");
}
}
}
}

View file

@ -1,127 +0,0 @@
/*
TShock, a server mod for Terraria
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using JsonLoader;
using Newtonsoft.Json;
namespace TShockAPI.PluginUpdater
{
public class PluginVersionCheck
{
public delegate void PluginUpdateD(UpdateArgs e);
public static event PluginUpdateD PluginUpdate;
public static void OnPluginUpdate(UpdateArgs args)
{
if (PluginUpdate == null)
{
return;
}
PluginUpdate(args);
}
public static void CheckPlugin(object p)
{
TerrariaPlugin plugin = (TerrariaPlugin)p;
UpdateArgs args = new UpdateArgs {Plugin = plugin, Success = true, Error = ""};
List<string> files = new List<string>();
try
{
if (!String.IsNullOrEmpty(plugin.UpdateURL))
{
var request = HttpWebRequest.Create(plugin.UpdateURL);
VersionInfo vi;
request.Timeout = 5000;
using (var response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
vi = JsonConvert.DeserializeObject<VersionInfo>(reader.ReadToEnd());
}
}
System.Version v = System.Version.Parse((vi.version.ToString()));
if (!v.Equals(plugin.Version))
{
DownloadPackage pkg;
request = HttpWebRequest.Create(vi.url);
request.Timeout = 5000;
using (var response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
pkg = JsonConvert.DeserializeObject<DownloadPackage>(reader.ReadToEnd());
}
}
foreach (PluginFile f in pkg.files)
{
using (WebClient Client = new WebClient())
{
string dir = Path.Combine(TShock.SavePath, "UpdatedPlugins");
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
Client.DownloadFile(f.url,
Path.Combine(dir, f.destination));
files.Add(Path.Combine(dir, f.destination));
}
}
}
else
{
args.Error = "Plugin is up to date.";
}
}
else
{
args.Error = "Plugin has no updater recorded.";
}
}
catch(Exception e)
{
args.Success = false;
args.Error = e.Message;
if(files.Count > 0)
{
foreach(string s in files)
{
File.Delete(s);
}
}
}
OnPluginUpdate(args);
}
}
public class UpdateArgs
{
public TerrariaPlugin Plugin { get; set; }
public bool Success { get; set; }
public string Error { get; set; }
}
}

View file

@ -1,87 +0,0 @@
/*
TShock, a server mod for Terraria
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
namespace JsonLoader
{
class VersionInfo
{
public Version version;
public string url;
}
public class Version
{
public int Major;
public int Minor;
public int Build;
public int Revision;
public int MajorRevision;
public int MinorRevision;
public Version()
{
SetVersion(0,0,0,0);
}
public Version(int m)
{
SetVersion(m, 0, 0, 0);
}
public Version(int ma, int mi)
{
SetVersion(ma, mi, 0, 0);
}
public Version(int ma, int mi, int b)
{
SetVersion(ma, mi, b, 0);
}
public Version(int ma, int mi, int b, int r)
{
SetVersion(ma, mi, b, r);
}
private void SetVersion(int ma, int mi, int b, int r)
{
Major = ma;
Minor = mi;
Build = b;
Revision = r;
}
public string ToString()
{
return String.Format("{0}.{1}.{2}.{3}", Major, Minor, Build, Revision);
}
}
class DownloadPackage
{
public List<PluginFile> files;
}
class PluginFile
{
public string url;
public string destination = "";
}
}

View file

@ -307,7 +307,7 @@ namespace TShockAPI
return RestMissingParam("password");
// NOTE: ip can be blank
User user = new User(username, password, group, "", "");
User user = new User(username, password, group, "", "", "");
try
{
TShock.Users.AddUser(user);

View file

@ -20,6 +20,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using Terraria;
using TerrariaApi.Server;
namespace TShockAPI
{
@ -45,7 +46,7 @@ namespace TShockAPI
/// <summary>
/// SaveWorld event handler which notifies users that the server may lag
/// </summary>
public void OnSaveWorld(bool resettime = false, HandledEventArgs e = null)
public void OnSaveWorld(WorldSaveEventArgs args)
{
// Protect against internal errors causing save failures
// These can be caused by an unexpected error such as a bad or out of date plugin
@ -120,7 +121,7 @@ namespace TShockAPI
{
if (task.direct)
{
OnSaveWorld();
OnSaveWorld(new WorldSaveEventArgs());
WorldGen.realsaveWorld(task.resetTime);
}
else

View file

@ -57,16 +57,21 @@ namespace TShockAPI
/// The number of projectiles created by the player in the last second.
/// </summary>
public int ProjectileThreshold { get; set; }
/// <summary>
/// A timer to keep track of whether or not the player has recently thrown an explosive
// </summary>
public int RecentFuse = 0;
/// <summary>
/// A queue of tiles destroyed by the player for reverting.
/// </summary>
public Dictionary<Vector2, TileData> TilesDestroyed { get; protected set; }
public Dictionary<Vector2, Tile> TilesDestroyed { get; protected set; }
/// <summary>
/// A queue of tiles placed by the player for reverting.
/// </summary>
public Dictionary<Vector2, TileData> TilesCreated { get; protected set; }
public Dictionary<Vector2, Tile> TilesCreated { get; protected set; }
public int FirstMaxHP { get; set; }
@ -390,7 +395,7 @@ namespace TShockAPI
bool flag = false;
if (RealPlayer)
{
for (int i = 0; i < 40; i++) //41 is trash can, 42-45 is coins, 46-49 is ammo
for (int i = 0; i < 50; i++) //51 is trash can, 52-55 is coins, 56-59 is ammo
{
if (TPlayer.inventory[i] == null || !TPlayer.inventory[i].active || TPlayer.inventory[i].name == "")
{
@ -405,8 +410,8 @@ namespace TShockAPI
public TSPlayer(int index)
{
TilesDestroyed = new Dictionary<Vector2, TileData>();
TilesCreated = new Dictionary<Vector2, TileData>();
TilesDestroyed = new Dictionary<Vector2, Tile>();
TilesCreated = new Dictionary<Vector2, Tile>();
Index = index;
Group = Group.DefaultGroup;
IceTiles = new List<Point>();
@ -415,8 +420,8 @@ namespace TShockAPI
protected TSPlayer(String playerName)
{
TilesDestroyed = new Dictionary<Vector2, TileData>();
TilesCreated = new Dictionary<Vector2, TileData>();
TilesDestroyed = new Dictionary<Vector2, Tile>();
TilesCreated = new Dictionary<Vector2, Tile>();
Index = -1;
FakePlayer = new Player {name = playerName, whoAmi = -1};
Group = Group.DefaultGroup;
@ -457,12 +462,47 @@ namespace TShockAPI
//Sending a fake world id causes the client to not be able to find a stored spawnx/y.
//This fixes the bed spawn point bug. With a fake world id it wont be able to find the bed spawn.
WorldID = !fakeid ? Main.worldID : -1,
WorldFlags = (WorldGen.shadowOrbSmashed ? WorldInfoFlag.OrbSmashed : WorldInfoFlag.None) |
(NPC.downedBoss1 ? WorldInfoFlag.DownedBoss1 : WorldInfoFlag.None) |
(NPC.downedBoss2 ? WorldInfoFlag.DownedBoss2 : WorldInfoFlag.None) |
(NPC.downedBoss3 ? WorldInfoFlag.DownedBoss3 : WorldInfoFlag.None) |
(Main.hardMode ? WorldInfoFlag.HardMode : WorldInfoFlag.None) |
(NPC.downedClown ? WorldInfoFlag.DownedClown : WorldInfoFlag.None),
MoonType = (byte)Main.moonType,
TreeX0 = Main.treeX[0],
TreeX1 = Main.treeX[1],
TreeX2 = Main.treeX[2],
TreeStyle0 = (byte)Main.treeStyle[0],
TreeStyle1 = (byte)Main.treeStyle[1],
TreeStyle2 = (byte)Main.treeStyle[2],
TreeStyle3 = (byte)Main.treeStyle[3],
CaveBackX0 = Main.caveBackX[0],
CaveBackX1 = Main.caveBackX[1],
CaveBackX2 = Main.caveBackX[2],
CaveBackStyle0 = (byte)Main.caveBackStyle[0],
CaveBackStyle1 = (byte)Main.caveBackStyle[1],
CaveBackStyle2 = (byte)Main.caveBackStyle[2],
CaveBackStyle3 = (byte)Main.caveBackStyle[3],
SetBG0 = (byte)WorldGen.treeBG,
SetBG1 = (byte)WorldGen.corruptBG,
SetBG2 = (byte)WorldGen.jungleBG,
SetBG3 = (byte)WorldGen.snowBG,
SetBG4 = (byte)WorldGen.hallowBG,
SetBG5 = (byte)WorldGen.crimsonBG,
SetBG6 = (byte)WorldGen.desertBG,
SetBG7 = (byte)WorldGen.oceanBG,
IceBackStyle = (byte)Main.iceBackStyle,
JungleBackStyle = (byte)Main.jungleBackStyle,
HellBackStyle = (byte)Main.hellBackStyle,
WindSpeed = Main.windSpeed,
NumberOfClouds = (byte)Main.numClouds,
BossFlags = (WorldGen.shadowOrbSmashed ? BossFlags.OrbSmashed : BossFlags.None) |
(NPC.downedBoss1 ? BossFlags.DownedBoss1 : BossFlags.None) |
(NPC.downedBoss2 ? BossFlags.DownedBoss2 : BossFlags.None) |
(NPC.downedBoss3 ? BossFlags.DownedBoss3 : BossFlags.None) |
(Main.hardMode ? BossFlags.HardMode : BossFlags.None) |
(NPC.downedClown ? BossFlags.DownedClown : BossFlags.None),
BossFlags2 = (NPC.downedMechBoss1 ? BossFlags2.DownedMechBoss1 : BossFlags2.None) |
(NPC.downedMechBoss2 ? BossFlags2.DownedMechBoss2 : BossFlags2.None) |
(NPC.downedMechBoss3 ? BossFlags2.DownedMechBoss3 : BossFlags2.None) |
(NPC.downedMechBossAny ? BossFlags2.DownedMechBossAny : BossFlags2.None) |
(Main.cloudBGActive == 1f ? BossFlags2.CloudBg : BossFlags2.None) |
(WorldGen.crimson ? BossFlags2.Crimson : BossFlags2.None),
Rain = Main.maxRaining,
WorldName = TShock.Config.UseServerName ? TShock.Config.ServerName : Main.worldName
};
msg.PackFull(ms);
@ -470,41 +510,35 @@ namespace TShockAPI
}
}
public bool Teleport(int tilex, int tiley)
public bool Teleport(float x, float y, byte style = 1)
{
InitSpawn = false;
SendWorldInfo(tilex, tiley, true);
//150 Should avoid all client crash errors
//The error occurs when a tile trys to update which the client hasnt load yet, Clients only update tiles withen 150 blocks
//Try 300 if it does not work (Higher number - Longer load times - Less chance of error)
//Should we properly send sections so that clients don't get tiles twice?
SendTileSquare(tilex, tiley, 150);
/* //We shouldn't need this section anymore -it can prevent otherwise acceptable teleportation under some circumstances.
if (!SendTileSquare(tilex, tiley, 150))
if (x > Main.rightWorld - 992)
{
InitSpawn = true;
SendWorldInfo(Main.spawnTileX, Main.spawnTileY, false);
return false;
x = Main.rightWorld - 992;
}
if (x < 992)
{
x = 992;
}
if (y > Main.bottomWorld - 992)
{
y = Main.bottomWorld - 992;
}
if (y < 992)
{
y = 992;
}
*/
Spawn(-1, -1);
SendWorldInfo(Main.spawnTileX, Main.spawnTileY, false);
TPlayer.position.X = (float)(tilex * 16 + 8 - TPlayer.width /2);
TPlayer.position.Y = (float)(tiley * 16 - TPlayer.height);
//We need to send the tile data again to prevent clients from thinking they *really* destroyed blocks just now.
SendTileSquare(tilex, tiley, 10);
TPlayer.Teleport(new Vector2(x, y), style);
NetMessage.SendData((int)PacketTypes.Teleport, -1, -1, "", 0, TPlayer.whoAmi, x, y, style);
return true;
}
public void Heal(int damage = 400)
{
NetMessage.SendData((int)PacketTypes.PlayerHealOther, -1, -1, "", this.TPlayer.whoAmi, damage);
}
public void Spawn()
{
Spawn(TPlayer.SpawnX, TPlayer.SpawnY);
@ -594,7 +628,7 @@ namespace TShockAPI
public virtual void GiveItem(int type, string name, int width, int height, int stack, int prefix = 0)
{
int itemid = Item.NewItem((int) X, (int) Y, width, height, type, stack, true, prefix);
int itemid = Item.NewItem((int) X, (int) Y, width, height, type, stack, true, prefix, true);
// This is for special pickaxe/hammers/swords etc
Main.item[itemid].SetDefaults(name);
@ -604,8 +638,10 @@ namespace TShockAPI
Main.item[itemid].stack = stack;
Main.item[itemid].owner = Index;
Main.item[itemid].prefix = (byte) prefix;
NetMessage.SendData((int) PacketTypes.ItemDrop, -1, -1, "", itemid, 0f, 0f, 0f);
NetMessage.SendData((int) PacketTypes.ItemOwner, -1, -1, "", itemid, 0f, 0f, 0f);
Main.item[itemid].noGrabDelay = 1;
Main.item[itemid].velocity = Main.player[this.Index].velocity;
NetMessage.SendData((int)PacketTypes.ItemDrop, -1, -1, "", itemid, 0f, 0f, 0f);
NetMessage.SendData((int)PacketTypes.ItemOwner, -1, -1, "", itemid, 0f, 0f, 0f);
}
public virtual void SendInfoMessage(string msg)
@ -876,6 +912,12 @@ namespace TShockAPI
Main.bloodMoon = bloodMoon;
SetTime(false, 0);
}
public void SetEclipse(bool Eclipse)
{
Main.eclipse = Eclipse;
SetTime(true, 150);
}
public void SetTime(bool dayTime, double time)
{
@ -910,12 +952,12 @@ namespace TShockAPI
NetMessage.SendData((int) PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
}
public void RevertTiles(Dictionary<Vector2, TileData> tiles)
public void RevertTiles(Dictionary<Vector2, Tile> tiles)
{
// Update Main.Tile first so that when tile sqaure is sent it is correct
foreach (KeyValuePair<Vector2, TileData> entry in tiles)
foreach (KeyValuePair<Vector2, Tile> entry in tiles)
{
Main.tile[(int) entry.Key.X, (int) entry.Key.Y].Data = entry.Value;
Main.tile[(int) entry.Key.X, (int) entry.Key.Y] = entry.Value;
}
// Send all players updated tile sqaures
foreach (Vector2 coords in tiles.Keys)
@ -977,9 +1019,10 @@ namespace TShockAPI
this.maxHealth = player.TPlayer.statLifeMax;
Item[] inventory = player.TPlayer.inventory;
Item[] armor = player.TPlayer.armor;
Item[] dye = player.TPlayer.dye;
for (int i = 0; i < NetItem.maxNetInventory; i++)
{
if (i < 49)
if (i < NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))
{
if (player.TPlayer.inventory[i] != null)
{
@ -1001,11 +1044,12 @@ namespace TShockAPI
this.inventory[i].prefix = 0;
}
}
else
else if (i < NetItem.maxNetInventory - NetItem.dyeSlots)
{
if (player.TPlayer.armor[i - 48] != null)
var index = i - (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots));
if (player.TPlayer.armor[index] != null)
{
this.inventory[i].netID = armor[i - 48].netID;
this.inventory[i].netID = armor[index].netID;
}
else
{
@ -1014,8 +1058,31 @@ namespace TShockAPI
if (this.inventory[i].netID != 0)
{
this.inventory[i].stack = armor[i - 48].stack;
this.inventory[i].prefix = armor[i - 48].prefix;
this.inventory[i].stack = armor[index].stack;
this.inventory[i].prefix = armor[index].prefix;
}
else
{
this.inventory[i].stack = 0;
this.inventory[i].prefix = 0;
}
}
else
{
var index = i - (NetItem.maxNetInventory - NetItem.dyeSlots);
if (player.TPlayer.dye[index] != null)
{
this.inventory[i].netID = armor[index].netID;
}
else
{
this.inventory[i].netID = 0;
}
if (this.inventory[i].netID != 0)
{
this.inventory[i].stack = armor[index].stack;
this.inventory[i].prefix = armor[index].prefix;
}
else
{
@ -1029,11 +1096,13 @@ namespace TShockAPI
public class NetItem
{
public static int maxNetInventory = 59;
public static readonly int maxNetInventory = 73;
public static readonly int armorSlots = 11;
public static readonly int dyeSlots = 3;
public int netID;
public int stack;
public int prefix;
public static string ToString(NetItem[] inventory)
{
string inventoryString = "";

View file

@ -27,19 +27,19 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using Hooks;
using MaxMind;
using Mono.Data.Sqlite;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Rests;
using Terraria;
using TerrariaApi.Server;
using TShockAPI.DB;
using TShockAPI.Net;
namespace TShockAPI
{
[APIVersion(1, 13)]
[ApiVersion(1, 14)]
public class TShock : TerrariaPlugin
{
public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version;
@ -231,25 +231,25 @@ namespace TShockAPI
Log.ConsoleInfo(string.Format("|> Version {0} ({1}) now running.", Version, VersionCodename));
GameHooks.PostInitialize += OnPostInit;
GameHooks.Update += OnUpdate;
GameHooks.HardUpdate += OnHardUpdate;
GameHooks.StatueSpawn += OnStatueSpawn;
ServerHooks.Connect += OnConnect;
ServerHooks.Join += OnJoin;
ServerHooks.Leave += OnLeave;
ServerHooks.Chat += OnChat;
ServerHooks.Command += ServerHooks_OnCommand;
NetHooks.GetData += OnGetData;
NetHooks.SendData += NetHooks_SendData;
NetHooks.GreetPlayer += OnGreetPlayer;
NpcHooks.StrikeNpc += NpcHooks_OnStrikeNpc;
NpcHooks.SetDefaultsInt += OnNpcSetDefaults;
ProjectileHooks.SetDefaults += OnProjectileSetDefaults;
WorldHooks.StartHardMode += OnStartHardMode;
WorldHooks.SaveWorld += SaveManager.Instance.OnSaveWorld;
WorldHooks.ChristmasCheck += OnXmasCheck;
NetHooks.NameCollision += NetHooks_NameCollision;
ServerApi.Hooks.GamePostInitialize.Register(this, OnPostInit);
ServerApi.Hooks.GameUpdate.Register(this, OnUpdate);
ServerApi.Hooks.GameHardmodeTileUpdate.Register(this, OnHardUpdate);
ServerApi.Hooks.GameStatueSpawn.Register(this, OnStatueSpawn);
ServerApi.Hooks.ServerConnect.Register(this, OnConnect);
ServerApi.Hooks.ServerJoin.Register(this, OnJoin);
ServerApi.Hooks.ServerLeave.Register(this, OnLeave);
ServerApi.Hooks.ServerChat.Register(this, OnChat);
ServerApi.Hooks.ServerCommand.Register(this, ServerHooks_OnCommand);
ServerApi.Hooks.NetGetData.Register(this, OnGetData);
ServerApi.Hooks.NetSendData.Register(this, NetHooks_SendData);
ServerApi.Hooks.NetGreetPlayer.Register(this, OnGreetPlayer);
ServerApi.Hooks.NpcStrike.Register(this, NpcHooks_OnStrikeNpc);
ServerApi.Hooks.NpcSetDefaultsInt.Register(this, OnNpcSetDefaults);
ServerApi.Hooks.ProjectileSetDefaults.Register(this, OnProjectileSetDefaults);
ServerApi.Hooks.WorldStartHardMode.Register(this, OnStartHardMode);
ServerApi.Hooks.WorldSave.Register(this, SaveManager.Instance.OnSaveWorld);
ServerApi.Hooks.WorldChristmasCheck.Register(this, OnXmasCheck);
ServerApi.Hooks.NetNameCollision.Register(this, NetHooks_NameCollision);
TShockAPI.Hooks.PlayerHooks.PlayerPostLogin += OnPlayerLogin;
GetDataHandlers.InitGetDataHandler();
@ -260,7 +260,7 @@ namespace TShockAPI
RestApi.Start();
if (Config.BufferPackets)
PacketBuffer = new PacketBufferer();
PacketBuffer = new PacketBufferer(this);
Log.ConsoleInfo("AutoSave " + (Config.AutoSave ? "Enabled" : "Disabled"));
Log.ConsoleInfo("Backups " + (Backups.Interval > 0 ? "Enabled" : "Disabled"));
@ -306,25 +306,26 @@ namespace TShockAPI
}
SaveManager.Instance.Dispose();
GameHooks.PostInitialize -= OnPostInit;
GameHooks.Update -= OnUpdate;
GameHooks.HardUpdate -= OnHardUpdate;
GameHooks.StatueSpawn -= OnStatueSpawn;
ServerHooks.Connect -= OnConnect;
ServerHooks.Join -= OnJoin;
ServerHooks.Leave -= OnLeave;
ServerHooks.Chat -= OnChat;
ServerHooks.Command -= ServerHooks_OnCommand;
NetHooks.GetData -= OnGetData;
NetHooks.SendData -= NetHooks_SendData;
NetHooks.GreetPlayer -= OnGreetPlayer;
NpcHooks.StrikeNpc -= NpcHooks_OnStrikeNpc;
NpcHooks.SetDefaultsInt -= OnNpcSetDefaults;
ProjectileHooks.SetDefaults -= OnProjectileSetDefaults;
WorldHooks.StartHardMode -= OnStartHardMode;
WorldHooks.SaveWorld -= SaveManager.Instance.OnSaveWorld;
WorldHooks.ChristmasCheck -= OnXmasCheck;
NetHooks.NameCollision -= NetHooks_NameCollision;
ServerApi.Hooks.GamePostInitialize.Deregister(this, OnPostInit);
ServerApi.Hooks.GameUpdate.Deregister(this, OnUpdate);
ServerApi.Hooks.GameHardmodeTileUpdate.Deregister(this, OnHardUpdate);
ServerApi.Hooks.GameStatueSpawn.Deregister(this, OnStatueSpawn);
ServerApi.Hooks.ServerConnect.Deregister(this, OnConnect);
ServerApi.Hooks.ServerJoin.Deregister(this, OnJoin);
ServerApi.Hooks.ServerLeave.Deregister(this, OnLeave);
ServerApi.Hooks.ServerChat.Deregister(this, OnChat);
ServerApi.Hooks.ServerCommand.Deregister(this, ServerHooks_OnCommand);
ServerApi.Hooks.NetGetData.Deregister(this, OnGetData);
ServerApi.Hooks.NetSendData.Deregister(this, NetHooks_SendData);
ServerApi.Hooks.NetGreetPlayer.Deregister(this, OnGreetPlayer);
ServerApi.Hooks.NpcStrike.Deregister(this, NpcHooks_OnStrikeNpc);
ServerApi.Hooks.NpcSetDefaultsInt.Deregister(this, OnNpcSetDefaults);
ServerApi.Hooks.ProjectileSetDefaults.Deregister(this, OnProjectileSetDefaults);
ServerApi.Hooks.WorldStartHardMode.Deregister(this, OnStartHardMode);
ServerApi.Hooks.WorldSave.Deregister(this, SaveManager.Instance.OnSaveWorld);
ServerApi.Hooks.WorldChristmasCheck.Deregister(this, OnXmasCheck);
ServerApi.Hooks.NetNameCollision.Deregister(this, NetHooks_NameCollision);
TShockAPI.Hooks.PlayerHooks.PlayerPostLogin -= OnPlayerLogin;
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
@ -362,34 +363,34 @@ namespace TShockAPI
Users.UpdateLogin(u);
}
private void NetHooks_NameCollision(int who, string name, HandledEventArgs e)
private void NetHooks_NameCollision(NameCollisionEventArgs args)
{
string ip = TShock.Utils.GetRealIP(Netplay.serverSock[who].tcpClient.Client.RemoteEndPoint.ToString());
string ip = TShock.Utils.GetRealIP(Netplay.serverSock[args.Who].tcpClient.Client.RemoteEndPoint.ToString());
foreach (TSPlayer ply in TShock.Players)
{
if (ply == null)
{
continue;
}
if (ply.Name == name && ply.Index != who)
if (ply.Name == args.Name && ply.Index != args.Who)
{
if (ply.IP == ip)
{
if (ply.State < 2)
{
Utils.ForceKick(ply, "Name collision and this client has no world data.", true, false);
e.Handled = true;
args.Handled = true;
return;
}
else
{
e.Handled = false;
args.Handled = false;
return;
}
}
}
}
e.Handled = false;
args.Handled = false;
return;
}
@ -533,7 +534,7 @@ namespace TShockAPI
public static int AuthToken = -1;
private void OnPostInit()
private void OnPostInit(EventArgs args)
{
SetConsoleTitle();
if (!File.Exists(Path.Combine(SavePath, "auth.lck")) && !File.Exists(Path.Combine(SavePath, "authcode.txt")))
@ -597,7 +598,7 @@ namespace TShockAPI
private DateTime LastCheck = DateTime.UtcNow;
private DateTime LastSave = DateTime.UtcNow;
private void OnUpdate()
private void OnUpdate(EventArgs args)
{
UpdateManager.UpdateProcedureCheck();
if (Backups.IsBackupTime)
@ -608,7 +609,7 @@ namespace TShockAPI
OnSecondUpdate();
LastCheck = DateTime.UtcNow;
}
if ((DateTime.UtcNow - LastSave).TotalMinutes >= Config.ServerSideInventorySave)
{
foreach (TSPlayer player in Players)
@ -638,12 +639,11 @@ namespace TShockAPI
break;
}
}
int count = 0;
foreach (TSPlayer player in Players)
{
if (player != null && player.Active)
{
count++;
if (player.TilesDestroyed != null)
{
if (player.TileKillThreshold >= Config.TileKillThreshold)
@ -672,6 +672,10 @@ namespace TShockAPI
{
player.TilePlaceThreshold = 0;
}
if (player.RecentFuse >0)
player.RecentFuse--;
if (player.TileLiquidThreshold >= Config.TileLiquidThreshold)
{
player.Disable("Reached TileLiquid threshold.");
@ -737,7 +741,7 @@ namespace TShockAPI
Config.MaxSlots, Netplay.serverListenIP, Netplay.serverPort, Version);
}
private void OnHardUpdate( HardUpdateEventArgs args )
private void OnHardUpdate(HardmodeTileUpdateEventArgs args)
{
if (args.Handled)
return;
@ -767,14 +771,14 @@ namespace TShockAPI
}
}
private void OnConnect(int ply, HandledEventArgs handler)
private void OnConnect(ConnectEventArgs args)
{
var player = new TSPlayer(ply);
var player = new TSPlayer(args.Who);
if (Utils.ActivePlayers() + 1 > Config.MaxSlots + Config.ReservedSlots)
{
Utils.ForceKick(player, Config.ServerFullNoReservedReason, true, false);
handler.Handled = true;
args.Handled = true;
return;
}
@ -790,7 +794,7 @@ namespace TShockAPI
DateTime exp;
string duration = DateTime.TryParse(ban.Expiration, out exp) ? String.Format("until {0}", exp.ToString("G")) : "forever";
Utils.ForceKick(player, string.Format("You are banned {0}: {1}", duration, ban.Reason), true, false);
handler.Handled = true;
args.Handled = true;
return;
}
}
@ -798,7 +802,7 @@ namespace TShockAPI
if (!FileTools.OnWhitelist(player.IP))
{
Utils.ForceKick(player, Config.WhitelistKickReason, true, false);
handler.Handled = true;
args.Handled = true;
return;
}
@ -811,20 +815,20 @@ namespace TShockAPI
if (Config.KickProxyUsers)
{
Utils.ForceKick(player, "Proxies are not allowed.", true, false);
handler.Handled = true;
args.Handled = true;
return;
}
}
}
Players[ply] = player;
Players[args.Who] = player;
}
private void OnJoin(int ply, HandledEventArgs handler)
private void OnJoin(JoinEventArgs args)
{
var player = Players[ply];
var player = Players[args.Who];
if (player == null)
{
handler.Handled = true;
args.Handled = true;
return;
}
@ -848,16 +852,16 @@ namespace TShockAPI
DateTime exp;
string duration = DateTime.TryParse(ban.Expiration, out exp) ? String.Format("until {0}", exp.ToString("G")) : "forever";
Utils.ForceKick(player, string.Format("You are banned {0}: {1}", duration, ban.Reason), true, false);
handler.Handled = true;
args.Handled = true;
}
}
}
private void OnLeave(int ply)
private void OnLeave(LeaveEventArgs args)
{
var tsplr = Players[ply];
Players[ply] = null;
var tsplr = Players[args.Who];
Players[args.Who] = null;
if (tsplr != null && tsplr.ReceivedInfo)
{
@ -880,15 +884,15 @@ namespace TShockAPI
}
}
private void OnChat(messageBuffer msg, int ply, string text, HandledEventArgs e)
private void OnChat(ServerChatEventArgs args)
{
if (e.Handled)
if (args.Handled)
return;
var tsplr = Players[msg.whoAmI];
var tsplr = Players[args.Who];
if (tsplr == null)
{
e.Handled = true;
args.Handled = true;
return;
}
@ -898,11 +902,11 @@ namespace TShockAPI
return;
}*/
if (text.StartsWith("/"))
if (args.Text.StartsWith("/"))
{
try
{
e.Handled = Commands.HandleCommand(tsplr, text);
args.Handled = Commands.HandleCommand(tsplr, args.Text);
}
catch (Exception ex)
{
@ -913,18 +917,18 @@ namespace TShockAPI
else if (!tsplr.mute && !TShock.Config.EnableChatAboveHeads)
{
Utils.Broadcast(
String.Format(Config.ChatFormat, tsplr.Group.Name, tsplr.Group.Prefix, tsplr.Name, tsplr.Group.Suffix, text),
String.Format(Config.ChatFormat, tsplr.Group.Name, tsplr.Group.Prefix, tsplr.Name, tsplr.Group.Suffix, args.Text),
tsplr.Group.R, tsplr.Group.G, tsplr.Group.B);
e.Handled = true;
args.Handled = true;
} else if (!tsplr.mute && TShock.Config.EnableChatAboveHeads)
{
Utils.Broadcast(ply, String.Format(Config.ChatAboveHeadsFormat, tsplr.Group.Name, tsplr.Group.Prefix, tsplr.Name, tsplr.Group.Suffix, text), tsplr.Group.R, tsplr.Group.G, tsplr.Group.B);
e.Handled = true;
Utils.Broadcast(args.Who, String.Format(Config.ChatAboveHeadsFormat, tsplr.Group.Name, tsplr.Group.Prefix, tsplr.Name, tsplr.Group.Suffix, args.Text), tsplr.Group.R, tsplr.Group.G, tsplr.Group.B);
args.Handled = true;
}
else if (tsplr.mute)
{
tsplr.SendErrorMessage("You are muted!");
e.Handled = true;
args.Handled = true;
}
}
@ -933,9 +937,9 @@ namespace TShockAPI
/// </summary>
/// <param name="cmd"></param>
/// <param name="e"></param>
private void ServerHooks_OnCommand(string text, HandledEventArgs e)
private void ServerHooks_OnCommand(CommandEventArgs args)
{
if (e.Handled)
if (args.Handled)
return;
// Damn you ThreadStatic and Redigit
@ -948,7 +952,7 @@ namespace TShockAPI
WorldGen.genRand = new Random();
}
if (text.StartsWith("playing") || text.StartsWith("/playing"))
if (args.Command.StartsWith("playing") || args.Command.StartsWith("/playing"))
{
int count = 0;
foreach (TSPlayer player in Players)
@ -962,20 +966,20 @@ namespace TShockAPI
}
TSPlayer.Server.SendInfoMessage(string.Format("{0} players connected.", count));
}
else if (text == "autosave")
else if (args.Command == "autosave")
{
Main.autoSave = Config.AutoSave = !Config.AutoSave;
Log.ConsoleInfo("AutoSave " + (Config.AutoSave ? "Enabled" : "Disabled"));
}
else if (text.StartsWith("/"))
else if (args.Command.StartsWith("/"))
{
Commands.HandleCommand(TSPlayer.Server, text);
Commands.HandleCommand(TSPlayer.Server, args.Command);
}
else
{
Commands.HandleCommand(TSPlayer.Server, "/" + text);
Commands.HandleCommand(TSPlayer.Server, "/" + args.Command);
}
e.Handled = true;
args.Handled = true;
}
private void OnGetData(GetDataEventArgs e)
@ -1027,12 +1031,12 @@ namespace TShockAPI
}
}
private void OnGreetPlayer(int who, HandledEventArgs e)
private void OnGreetPlayer(GreetPlayerEventArgs args)
{
var player = Players[who];
var player = Players[args.Who];
if (player == null)
{
e.Handled = true;
args.Handled = true;
return;
}
player.LoginMS= DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
@ -1072,10 +1076,13 @@ namespace TShockAPI
if (RememberedPos.GetLeavePos(player.Name, player.IP) != Vector2.Zero){
var pos = RememberedPos.GetLeavePos(player.Name, player.IP);
player.Teleport((int) pos.X, (int) pos.Y + 3);
player.Teleport(pos.X*16, pos.Y*16 + 48);
}}
e.Handled = true;
Item i = new Item();
i.SetDefaults("Confetti Gun");
player.GiveItem(i.type, i.name, i.width, i.headSlot, 10);
args.Handled = true;
}
private void NpcHooks_OnStrikeNpc(NpcStrikeEventArgs e)
@ -1152,7 +1159,7 @@ namespace TShockAPI
private void NetHooks_SendData(SendDataEventArgs e)
{
if (e.MsgID == PacketTypes.Disconnect)
if (e.MsgId == PacketTypes.Disconnect)
{
Action<ServerSock, string> senddisconnect = (sock, str) =>
{
@ -1182,7 +1189,7 @@ namespace TShockAPI
}
e.Handled = true;
}
if (e.MsgID == PacketTypes.WorldInfo)
if (e.MsgId == PacketTypes.WorldInfo)
{
if (e.remoteClient == -1) return;
var player = Players[e.remoteClient];
@ -1193,26 +1200,62 @@ namespace TShockAPI
{
var msg = new WorldInfoMsg
{
Time = (int)Main.time,
DayTime = Main.dayTime,
MoonPhase = (byte)Main.moonPhase,
BloodMoon = Main.bloodMoon,
MaxTilesX = Main.maxTilesX,
MaxTilesY = Main.maxTilesY,
SpawnX = Main.spawnTileX,
SpawnY = Main.spawnTileY,
WorldSurface = (int)Main.worldSurface,
RockLayer = (int)Main.rockLayer,
WorldID = Main.worldID,
WorldFlags =
(WorldGen.shadowOrbSmashed ? WorldInfoFlag.OrbSmashed : WorldInfoFlag.None) |
(NPC.downedBoss1 ? WorldInfoFlag.DownedBoss1 : WorldInfoFlag.None) |
(NPC.downedBoss2 ? WorldInfoFlag.DownedBoss2 : WorldInfoFlag.None) |
(NPC.downedBoss3 ? WorldInfoFlag.DownedBoss3 : WorldInfoFlag.None) |
(Main.hardMode ? WorldInfoFlag.HardMode : WorldInfoFlag.None) |
(NPC.downedClown ? WorldInfoFlag.DownedClown : WorldInfoFlag.None),
WorldName = Config.ServerName
};
Time = (int) Main.time,
DayTime = Main.dayTime,
MoonPhase = (byte) Main.moonPhase,
BloodMoon = Main.bloodMoon,
MaxTilesX = Main.maxTilesX,
MaxTilesY = Main.maxTilesY,
SpawnX = Main.spawnTileX,
SpawnY = Main.spawnTileY,
WorldSurface = (int) Main.worldSurface,
RockLayer = (int) Main.rockLayer,
//Sending a fake world id causes the client to not be able to find a stored spawnx/y.
//This fixes the bed spawn point bug. With a fake world id it wont be able to find the bed spawn.
WorldID = Main.worldID,
MoonType = (byte)Main.moonType,
TreeX0 = Main.treeX[0],
TreeX1 = Main.treeX[1],
TreeX2 = Main.treeX[2],
TreeStyle0 = (byte)Main.treeStyle[0],
TreeStyle1 = (byte)Main.treeStyle[1],
TreeStyle2 = (byte)Main.treeStyle[2],
TreeStyle3 = (byte)Main.treeStyle[3],
CaveBackX0 = Main.caveBackX[0],
CaveBackX1 = Main.caveBackX[1],
CaveBackX2 = Main.caveBackX[2],
CaveBackStyle0 = (byte)Main.caveBackStyle[0],
CaveBackStyle1 = (byte)Main.caveBackStyle[1],
CaveBackStyle2 = (byte)Main.caveBackStyle[2],
CaveBackStyle3 = (byte)Main.caveBackStyle[3],
SetBG0 = (byte)WorldGen.treeBG,
SetBG1 = (byte)WorldGen.corruptBG,
SetBG2 = (byte)WorldGen.jungleBG,
SetBG3 = (byte)WorldGen.snowBG,
SetBG4 = (byte)WorldGen.hallowBG,
SetBG5 = (byte)WorldGen.crimsonBG,
SetBG6 = (byte)WorldGen.desertBG,
SetBG7 = (byte)WorldGen.oceanBG,
IceBackStyle = (byte)Main.iceBackStyle,
JungleBackStyle = (byte)Main.jungleBackStyle,
HellBackStyle = (byte)Main.hellBackStyle,
WindSpeed = Main.windSpeed,
NumberOfClouds = (byte)Main.numClouds,
BossFlags = (WorldGen.shadowOrbSmashed ? BossFlags.OrbSmashed : BossFlags.None) |
(NPC.downedBoss1 ? BossFlags.DownedBoss1 : BossFlags.None) |
(NPC.downedBoss2 ? BossFlags.DownedBoss2 : BossFlags.None) |
(NPC.downedBoss3 ? BossFlags.DownedBoss3 : BossFlags.None) |
(Main.hardMode ? BossFlags.HardMode : BossFlags.None) |
(NPC.downedClown ? BossFlags.DownedClown : BossFlags.None),
BossFlags2 = (NPC.downedMechBoss1 ? BossFlags2.DownedMechBoss1 : BossFlags2.None) |
(NPC.downedMechBoss2 ? BossFlags2.DownedMechBoss2 : BossFlags2.None) |
(NPC.downedMechBoss3 ? BossFlags2.DownedMechBoss3 : BossFlags2.None) |
(NPC.downedMechBossAny ? BossFlags2.DownedMechBossAny : BossFlags2.None) |
(Main.cloudBGActive == 1f ? BossFlags2.CloudBg : BossFlags2.None) |
(WorldGen.crimson ? BossFlags2.Crimson : BossFlags2.None),
Rain = Main.maxRaining,
WorldName = TShock.Config.UseServerName ? TShock.Config.ServerName : Main.worldName
};
msg.PackFull(ms);
player.SendRawData(ms.ToArray());
}
@ -1332,11 +1375,11 @@ namespace TShockAPI
return false;
}
public static bool CheckTilePermission( TSPlayer player, int tileX, int tileY, byte tileType, byte actionType )
public static bool CheckTilePermission( TSPlayer player, int tileX, int tileY, byte tileType, GetDataHandlers.EditAction actionType )
{
if (!player.Group.HasPermission(Permissions.canbuild))
{
if (TShock.Config.AllowIce && actionType != 1)
if (TShock.Config.AllowIce && actionType != GetDataHandlers.EditAction.PlaceTile)
{
foreach (Point p in player.IceTiles)
@ -1356,7 +1399,7 @@ namespace TShockAPI
return true;
}
if (TShock.Config.AllowIce && actionType == 1 && tileType == 127)
if (TShock.Config.AllowIce && actionType == GetDataHandlers.EditAction.PlaceTile && tileType == 127)
{
player.IceTiles.Add(new Point(tileX, tileY));
return false;
@ -1387,12 +1430,12 @@ namespace TShockAPI
{
if (!player.Group.HasPermission(Permissions.editspawn))
{
if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000){
player.SendMessage("The world is protected from changes.", Color.Red);
player.WPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
}
return true;
if (((DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond) - player.WPm) > 2000)
{
player.SendMessage("The world is protected from changes.", Color.Red);
player.WPm = DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond;
}
return true;
}
}
if (Config.SpawnProtection)
@ -1498,9 +1541,10 @@ namespace TShockAPI
Item[] inventory = player.TPlayer.inventory;
Item[] armor = player.TPlayer.armor;
Item[] dye = player.TPlayer.dye;
for (int i = 0; i < NetItem.maxNetInventory; i++)
{
if (i < 49)
if (i < NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))
{
Item item = new Item();
if (inventory[i] != null && inventory[i].netID != 0)
@ -1517,15 +1561,16 @@ namespace TShockAPI
}
}
}
else
else if(i < (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)))
{
Item item = new Item();
if (armor[i - 48] != null && armor[i - 48].netID != 0)
var index = i - (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots));
if (armor[index] != null && armor[index].netID != 0)
{
item.netDefaults(armor[i - 48].netID);
item.Prefix(armor[i - 48].prefix);
item.netDefaults(armor[index].netID);
item.Prefix(armor[index].prefix);
item.AffixName();
if (armor[i - 48].stack > item.maxStack)
if (armor[index].stack > item.maxStack)
{
check = true;
player.SendMessage(
@ -1534,6 +1579,24 @@ namespace TShockAPI
}
}
}
else if (i < (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)))
{
Item item = new Item();
var index = i - (NetItem.maxNetInventory - NetItem.dyeSlots);
if (dye[index] != null && dye[index].netID != 0)
{
item.netDefaults(dye[index].netID);
item.Prefix(dye[index].prefix);
item.AffixName();
if (dye[index].stack > item.maxStack)
{
check = true;
player.SendMessage(
String.Format("Stack cheat detected. Remove dye {0} ({1}) and then rejoin", item.name, dye[index].stack),
Color.Cyan);
}
}
}
}
return check;
@ -1553,9 +1616,10 @@ namespace TShockAPI
Item[] inventory = player.TPlayer.inventory;
Item[] armor = player.TPlayer.armor;
Item[] dye = player.TPlayer.dye;
for (int i = 0; i < NetItem.maxNetInventory; i++)
{
if (i < 49)
if (i < NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))
{
Item item = new Item();
Item serverItem = new Item();
@ -1592,34 +1656,35 @@ namespace TShockAPI
}
}
}
else
else if(i < (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)))
{
Item item = new Item();
Item serverItem = new Item();
if (armor[i - 48] != null && armor[i - 48].netID != 0)
var index = i - (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots));
if (armor[index] != null && armor[index].netID != 0)
{
if (playerData.inventory[i].netID != armor[i - 48].netID)
if (playerData.inventory[i].netID != armor[index].netID)
{
item.netDefaults(armor[i - 48].netID);
item.Prefix(armor[i - 48].prefix);
item.netDefaults(armor[index].netID);
item.Prefix(armor[index].prefix);
item.AffixName();
player.SendMessage(player.IgnoreActionsForInventory = "Your armor (" + item.name + ") needs to be deleted.",
Color.Cyan);
check = false;
}
else if (playerData.inventory[i].prefix != armor[i - 48].prefix)
else if (playerData.inventory[i].prefix != armor[index].prefix)
{
item.netDefaults(armor[i - 48].netID);
item.Prefix(armor[i - 48].prefix);
item.netDefaults(armor[index].netID);
item.Prefix(armor[index].prefix);
item.AffixName();
player.SendMessage(player.IgnoreActionsForInventory = "Your armor (" + item.name + ") needs to be deleted.",
Color.Cyan);
check = false;
}
else if (armor[i - 48].stack > playerData.inventory[i].stack)
else if (armor[index].stack > playerData.inventory[i].stack)
{
item.netDefaults(armor[i - 48].netID);
item.Prefix(armor[i - 48].prefix);
item.netDefaults(armor[index].netID);
item.Prefix(armor[index].prefix);
item.AffixName();
player.SendMessage(
player.IgnoreActionsForInventory =
@ -1629,6 +1694,44 @@ namespace TShockAPI
}
}
}
else if(i < (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots)))
{
Item item = new Item();
Item serverItem = new Item();
var index = i - (NetItem.maxNetInventory - NetItem.dyeSlots);
if (dye[index] != null && dye[index].netID != 0)
{
if (playerData.inventory[i].netID != dye[index].netID)
{
item.netDefaults(dye[index].netID);
item.Prefix(dye[index].prefix);
item.AffixName();
player.SendMessage(player.IgnoreActionsForInventory = "Your dye (" + item.name + ") needs to be deleted.",
Color.Cyan);
check = false;
}
else if (playerData.inventory[i].prefix != dye[index].prefix)
{
item.netDefaults(dye[index].netID);
item.Prefix(dye[index].prefix);
item.AffixName();
player.SendMessage(player.IgnoreActionsForInventory = "Your dye (" + item.name + ") needs to be deleted.",
Color.Cyan);
check = false;
}
else if (dye[index].stack > playerData.inventory[i].stack)
{
item.netDefaults(dye[index].netID);
item.Prefix(dye[index].prefix);
item.AffixName();
player.SendMessage(
player.IgnoreActionsForInventory =
"Your dye (" + item.name + ") (" + inventory[i].stack + ") needs to have its stack size decreased to (" +
playerData.inventory[i].stack + ").", Color.Cyan);
check = false;
}
}
}
}
return check;
@ -1636,20 +1739,7 @@ namespace TShockAPI
public static bool CheckIgnores(TSPlayer player)
{
bool check = false;
if (Config.PvPMode == "always" && !player.TPlayer.hostile)
check = true;
if (player.IgnoreActionsForInventory != "none")
check = true;
if (player.IgnoreActionsForCheating != "none")
check = true;
if (player.IgnoreActionsForDisabledArmor != "none")
check = true;
if (player.IgnoreActionsForClearingTrashCan)
check = true;
if (!player.IsLoggedIn && Config.RequireLogin)
check = true;
return check;
return Config.PvPMode == "always" && !player.TPlayer.hostile || player.IgnoreActionsForInventory != "none" || player.IgnoreActionsForCheating != "none" || player.IgnoreActionsForDisabledArmor != "none" || player.IgnoreActionsForClearingTrashCan || !player.IsLoggedIn && Config.RequireLogin;;
}
public void OnConfigRead(ConfigFile file)

View file

@ -38,6 +38,7 @@
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\TShockAPI.XML</DocumentationFile>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -67,7 +68,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="TerrariaServer, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="TerrariaServer, Version=1.14.0.0, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<ExecutableExtension>.exe</ExecutableExtension>
<HintPath>..\TerrariaServerBins\TerrariaServer.exe</HintPath>
@ -79,9 +80,6 @@
<Compile Include="Hooks\GeneralHooks.cs" />
<Compile Include="Hooks\PlayerHooks.cs" />
<Compile Include="PaginationTools.cs" />
<Compile Include="PluginUpdater\PluginUpdaterThread.cs" />
<Compile Include="PluginUpdater\PluginVersionCheck.cs" />
<Compile Include="PluginUpdater\VersionInfo.cs" />
<Compile Include="Rest\RestPermissions.cs" />
<Compile Include="SaveManager.cs" />
<Compile Include="DB\BanManager.cs" />

View file

@ -329,7 +329,7 @@ namespace TShockAPI
/// <returns>The state of the tile</returns>
private bool TileClear(int tileX, int tileY)
{
return !Main.tile[tileX, tileY].active;
return !Main.tile[tileX, tileY].active();
}
/// <summary>
@ -371,7 +371,7 @@ namespace TShockAPI
var found = new List<Item>();
Item item = new Item();
string nameLower = name.ToLower();
for (int i = -24; i < Main.maxItemTypes; i++)
for (int i = -48; i < Main.maxItemTypes; i++)
{
item.netDefaults(i);
if (item.name.ToLower() == nameLower)