Merge commit 'e465caa230' into general-devel-2
This commit is contained in:
commit
07de1159fd
37 changed files with 2597 additions and 1560 deletions
11
GUIDELINES
Normal file
11
GUIDELINES
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
These guidelines are for contributors. If you do not follow these guidelines your commits will be reverted.
|
||||
|
||||
Required:
|
||||
-Follow the code style. We generally use microsofts except for m_ infront of private variables.
|
||||
-Do not push unfinished features to the master branch, instead create a remote branch and push to that.
|
||||
-Do not push untested code to the master branch, instead push to the test branch.
|
||||
-Document all compatibility issues in the COMPATIBILITY file. (IE file formats changing)
|
||||
-DO NOT MASS COMMIT. Commit changes as you go (without pushing). That way when you push we don't get a thousand changes with a 1-3 line commit message.
|
||||
|
||||
Optional:
|
||||
-Build Version Increment (http://autobuildversion.codeplex.com/).
|
||||
98
TShockAPI/BackupManager.cs
Normal file
98
TShockAPI/BackupManager.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011 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.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Terraria;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
public class BackupManager
|
||||
{
|
||||
public string BackupPath { get; set; }
|
||||
public int Interval { get; set; }
|
||||
public int KeepFor { get; set; }
|
||||
|
||||
DateTime lastbackup = DateTime.UtcNow;
|
||||
public BackupManager(string path)
|
||||
{
|
||||
BackupPath = path;
|
||||
}
|
||||
|
||||
public bool IsBackupTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Interval > 0) && ((DateTime.UtcNow - lastbackup).TotalMinutes >= Interval);
|
||||
}
|
||||
}
|
||||
|
||||
public void Backup()
|
||||
{
|
||||
lastbackup = DateTime.UtcNow;
|
||||
ThreadPool.QueueUserWorkItem(DoBackup);
|
||||
ThreadPool.QueueUserWorkItem(DeleteOld);
|
||||
}
|
||||
|
||||
void DoBackup(object o)
|
||||
{
|
||||
try
|
||||
{
|
||||
string worldname = Main.worldPathName;
|
||||
string name = Path.GetFileName(worldname);
|
||||
|
||||
Main.worldPathName = Path.Combine(BackupPath, string.Format("{0}.{1:dd.MM.yy-HH.mm.ss}.bak", name, DateTime.UtcNow));
|
||||
|
||||
string worldpath = Path.GetDirectoryName(Main.worldPathName);
|
||||
if (worldpath != null && !Directory.Exists(worldpath))
|
||||
Directory.CreateDirectory(worldpath);
|
||||
|
||||
WorldGen.saveWorld();
|
||||
|
||||
Console.WriteLine("World backed up");
|
||||
Log.Info(string.Format("World backed up ({0})", Main.worldPathName));
|
||||
|
||||
Main.worldPathName = worldname;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Backup failed");
|
||||
Log.Error("Backup failed");
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteOld(object o)
|
||||
{
|
||||
if (KeepFor <= 0)
|
||||
return;
|
||||
foreach (var fi in new DirectoryInfo(BackupPath).GetFiles("*.bak"))
|
||||
{
|
||||
if ((DateTime.UtcNow - fi.LastWriteTimeUtc).TotalMinutes > KeepFor)
|
||||
{
|
||||
fi.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -30,10 +30,11 @@ namespace TShockAPI
|
|||
public bool BanCheaters = true;
|
||||
public bool KickGriefers = true;
|
||||
public bool BanGriefers = true;
|
||||
public bool BanKillTileAbusers;
|
||||
public bool KickKillTileAbusers;
|
||||
public bool BanKillTileAbusers = true;
|
||||
public bool KickKillTileAbusers = true;
|
||||
public bool BanExplosives = true;
|
||||
public bool KickExplosives = true;
|
||||
public bool DisableExplosives = true;
|
||||
public bool SpawnProtection = true;
|
||||
public int SpawnProtectionRadius = 5;
|
||||
public string DistributationAgent = "facepunch";
|
||||
|
|
@ -41,7 +42,22 @@ namespace TShockAPI
|
|||
public bool RangeChecks = true;
|
||||
public bool SpamChecks = false;
|
||||
public bool DisableBuild = false;
|
||||
public int TileThreshold = 20;
|
||||
|
||||
public float[] AdminChatRGB = {255, 0, 0};
|
||||
public string AdminChatPrefix = "(Admin) ";
|
||||
|
||||
public int PvpThrottle = 0;
|
||||
|
||||
public int BackupInterval = 0;
|
||||
public int BackupKeepFor = 60;
|
||||
|
||||
public bool RememberLeavePos = false;
|
||||
|
||||
public bool HardcoreOnly = false;
|
||||
public bool KickOnHardcoreOnlyDeath = false;
|
||||
public bool BanOnHardcoreOnlyDeath = false;
|
||||
|
||||
public bool AutoSave = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -44,6 +44,7 @@ namespace TShockAPI
|
|||
public static bool KickTnt = true;
|
||||
public static bool BanBoom = true;
|
||||
public static bool KickBoom = true;
|
||||
public static bool DisableBoom = true;
|
||||
public static bool SpawnProtect = true;
|
||||
public static bool RangeChecks = true;
|
||||
public static int SpawnProtectRadius = 5;
|
||||
|
|
@ -54,6 +55,28 @@ namespace TShockAPI
|
|||
public static bool DisableBuild = false;
|
||||
public static float[] AdminChatRGB = {255, 0, 0};
|
||||
public static string AdminChatPrefix = "(Admin) ";
|
||||
public static bool RememberLeavePos = false;
|
||||
public static int TileThreshold = 20;
|
||||
|
||||
/// <summary>
|
||||
/// Don't allow pvp changing for x seconds.
|
||||
/// </summary>
|
||||
public static int PvpThrottle = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Backup every x minutes
|
||||
/// </summary>
|
||||
public static int BackupInterval = 0;
|
||||
/// <summary>
|
||||
/// Delete backups that are older than x mintues.
|
||||
/// </summary>
|
||||
public static int BackupKeepFor = 60;
|
||||
|
||||
public static bool HardcoreOnly = false;
|
||||
public static bool KickOnHardcoreDeath = false;
|
||||
public static bool BanOnHardcoreDeath = false;
|
||||
|
||||
public static bool AutoSave = true;
|
||||
|
||||
public static void ReadJsonConfiguration()
|
||||
{
|
||||
|
|
@ -76,6 +99,7 @@ namespace TShockAPI
|
|||
KickTnt = cfg.KickKillTileAbusers;
|
||||
BanBoom = cfg.BanExplosives;
|
||||
KickBoom = cfg.KickExplosives;
|
||||
DisableBoom = cfg.DisableExplosives;
|
||||
SpawnProtect = cfg.SpawnProtection;
|
||||
SpawnProtectRadius = cfg.SpawnProtectionRadius;
|
||||
DistributationAgent = cfg.DistributationAgent;
|
||||
|
|
@ -83,10 +107,19 @@ namespace TShockAPI
|
|||
RangeChecks = cfg.RangeChecks;
|
||||
SpamChecks = cfg.SpamChecks;
|
||||
DisableBuild = cfg.DisableBuild;
|
||||
TileThreshold = cfg.TileThreshold;
|
||||
NPC.maxSpawns = DefaultMaxSpawns;
|
||||
NPC.defaultSpawnRate = DefaultSpawnRate;
|
||||
AdminChatRGB = cfg.AdminChatRGB;
|
||||
AdminChatPrefix = cfg.AdminChatPrefix;
|
||||
PvpThrottle = cfg.PvpThrottle;
|
||||
BackupInterval = cfg.BackupInterval;
|
||||
BackupKeepFor = cfg.BackupKeepFor;
|
||||
RememberLeavePos = cfg.RememberLeavePos;
|
||||
HardcoreOnly = cfg.HardcoreOnly;
|
||||
KickOnHardcoreDeath = cfg.KickOnHardcoreOnlyDeath;
|
||||
BanOnHardcoreDeath = cfg.BanOnHardcoreOnlyDeath;
|
||||
AutoSave = cfg.AutoSave;
|
||||
}
|
||||
|
||||
public static void WriteJsonConfiguration()
|
||||
|
|
@ -103,18 +136,28 @@ namespace TShockAPI
|
|||
cfg.BanCheaters = BanCheater;
|
||||
cfg.KickGriefers = KickGriefer;
|
||||
cfg.BanGriefers = BanGriefer;
|
||||
cfg.BanKillTileAbusers = BanGriefer;
|
||||
cfg.KickKillTileAbusers = KickGriefer;
|
||||
cfg.BanKillTileAbusers = BanTnt;
|
||||
cfg.KickKillTileAbusers = KickTnt;
|
||||
cfg.BanExplosives = BanBoom;
|
||||
cfg.KickExplosives = KickBoom;
|
||||
cfg.DisableExplosives = DisableBoom;
|
||||
cfg.SpawnProtection = SpawnProtect;
|
||||
cfg.SpawnProtectionRadius = SpawnProtectRadius;
|
||||
cfg.MaxSlots = MaxSlots;
|
||||
cfg.RangeChecks = RangeChecks;
|
||||
cfg.SpamChecks = SpamChecks;
|
||||
cfg.DisableBuild = DisableBuild;
|
||||
cfg.TileThreshold = TileThreshold;
|
||||
cfg.AdminChatRGB = AdminChatRGB;
|
||||
cfg.AdminChatPrefix = AdminChatPrefix;
|
||||
cfg.PvpThrottle = PvpThrottle;
|
||||
cfg.BackupInterval = BackupInterval;
|
||||
cfg.BackupKeepFor = BackupKeepFor;
|
||||
cfg.RememberLeavePos = RememberLeavePos;
|
||||
cfg.HardcoreOnly = HardcoreOnly;
|
||||
cfg.BanOnHardcoreOnlyDeath = BanOnHardcoreDeath;
|
||||
cfg.KickOnHardcoreOnlyDeath = KickOnHardcoreDeath;
|
||||
cfg.AutoSave = AutoSave;
|
||||
string json = JsonConvert.SerializeObject(cfg, Formatting.Indented);
|
||||
TextWriter tr = new StreamWriter(FileTools.ConfigPath);
|
||||
tr.Write(json);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@ namespace TShockAPI
|
|||
public static readonly string WhitelistPath = Path.Combine(TShock.SavePath, "whitelist.txt");
|
||||
public static readonly string GroupsPath = Path.Combine(TShock.SavePath, "groups.txt");
|
||||
public static readonly string UsersPath = Path.Combine(TShock.SavePath, "users.txt");
|
||||
public static readonly string ItemBansPath = Path.Combine(TShock.SavePath, "itembans.txt");
|
||||
public static readonly string RememberedPosPath = Path.Combine(TShock.SavePath, "oldpos.xml");
|
||||
public static readonly string ConfigPath = Path.Combine(TShock.SavePath, "config.json");
|
||||
public static readonly string RegionsPath = Path.Combine(TShock.SavePath, "regions.xml");
|
||||
public static readonly string WarpsPath = Path.Combine(TShock.SavePath, "warps.xml");
|
||||
|
||||
public static void CreateFile(string file)
|
||||
{
|
||||
|
|
@ -60,6 +64,25 @@ namespace TShockAPI
|
|||
CreateIfNot(WhitelistPath);
|
||||
CreateIfNot(GroupsPath, Resources.groups);
|
||||
CreateIfNot(UsersPath, Resources.users);
|
||||
CreateIfNot(ItemBansPath, Resources.itembans);
|
||||
|
||||
//Copies if using old paths (Remove in future releases, after everyone is running this version +)
|
||||
if (File.Exists("regions.xml") && !File.Exists(RegionsPath))
|
||||
{
|
||||
File.Move("regions.xml", RegionsPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateIfNot(RegionsPath);
|
||||
}
|
||||
if (File.Exists("warps.xml") && !File.Exists(WarpsPath))
|
||||
{
|
||||
File.Move("warps.xml", WarpsPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateIfNot(WarpsPath);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -100,7 +123,23 @@ namespace TShockAPI
|
|||
TextReader tr = new StreamReader(WhitelistPath);
|
||||
string whitelist = tr.ReadToEnd();
|
||||
ip = Tools.GetRealIP(ip);
|
||||
return whitelist.Contains(ip);
|
||||
bool contains = whitelist.Contains(ip);
|
||||
if (!contains)
|
||||
{
|
||||
var char2 = Environment.NewLine.ToCharArray();
|
||||
var array = whitelist.Split(Environment.NewLine.ToCharArray());
|
||||
foreach (var line in whitelist.Split(Environment.NewLine.ToCharArray()))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
contains = Tools.GetIPv4Address(line).Equals(ip);
|
||||
if (contains)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,426 +1,481 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011 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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework;
|
||||
using StreamBinary;
|
||||
using Terraria;
|
||||
using TerrariaAPI;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
public delegate bool GetDataHandlerDelegate(GetDataHandlerArgs args);
|
||||
public class GetDataHandlerArgs : EventArgs
|
||||
{
|
||||
public TSPlayer Player { get; private set; }
|
||||
public MemoryStream Data { get; private set; }
|
||||
|
||||
public Player TPlayer
|
||||
{
|
||||
get { return Player.TPlayer; }
|
||||
}
|
||||
|
||||
public GetDataHandlerArgs(TSPlayer player, MemoryStream data)
|
||||
{
|
||||
Player = player;
|
||||
Data = data;
|
||||
}
|
||||
}
|
||||
public static class GetDataHandlers
|
||||
{
|
||||
private static Dictionary<PacketTypes, GetDataHandlerDelegate> GetDataHandlerDelegates;
|
||||
private static bool[] BlacklistTiles;
|
||||
|
||||
public static void InitGetDataHandler()
|
||||
{
|
||||
#region Blacklisted tiles
|
||||
|
||||
BlacklistTiles = new bool[Main.maxTileSets];
|
||||
BlacklistTiles[0] = true;
|
||||
BlacklistTiles[1] = true;
|
||||
BlacklistTiles[2] = true;
|
||||
BlacklistTiles[6] = true;
|
||||
BlacklistTiles[7] = true;
|
||||
BlacklistTiles[8] = true;
|
||||
BlacklistTiles[9] = true;
|
||||
BlacklistTiles[22] = true;
|
||||
BlacklistTiles[23] = true;
|
||||
BlacklistTiles[25] = true;
|
||||
BlacklistTiles[30] = true;
|
||||
BlacklistTiles[37] = true;
|
||||
BlacklistTiles[38] = true;
|
||||
BlacklistTiles[39] = true;
|
||||
BlacklistTiles[40] = true;
|
||||
BlacklistTiles[41] = true;
|
||||
BlacklistTiles[43] = true;
|
||||
BlacklistTiles[44] = true;
|
||||
BlacklistTiles[45] = true;
|
||||
BlacklistTiles[46] = true;
|
||||
BlacklistTiles[47] = true;
|
||||
BlacklistTiles[53] = true;
|
||||
BlacklistTiles[54] = true;
|
||||
BlacklistTiles[56] = true;
|
||||
BlacklistTiles[57] = true;
|
||||
BlacklistTiles[58] = true;
|
||||
BlacklistTiles[59] = true;
|
||||
BlacklistTiles[60] = true;
|
||||
BlacklistTiles[63] = true;
|
||||
BlacklistTiles[64] = true;
|
||||
BlacklistTiles[65] = true;
|
||||
BlacklistTiles[66] = true;
|
||||
BlacklistTiles[67] = true;
|
||||
BlacklistTiles[68] = true;
|
||||
BlacklistTiles[70] = true;
|
||||
BlacklistTiles[75] = true;
|
||||
BlacklistTiles[76] = true;
|
||||
|
||||
#endregion Blacklisted tiles
|
||||
|
||||
GetDataHandlerDelegates = new Dictionary<PacketTypes, GetDataHandlerDelegate>
|
||||
{
|
||||
{PacketTypes.PlayerInfo, HandlePlayerInfo},
|
||||
{PacketTypes.TileSendSection, HandleSendSection},
|
||||
{PacketTypes.PlayerUpdate, HandlePlayerUpdate},
|
||||
{PacketTypes.Tile, HandleTile},
|
||||
{PacketTypes.TileSendSquare, HandleSendTileSquare},
|
||||
{PacketTypes.NPCUpdate, HandleNpcUpdate},
|
||||
{PacketTypes.PlayerDamage, HandlePlayerDamage},
|
||||
{PacketTypes.ProjectileNew, HandleProjectileNew},
|
||||
{PacketTypes.TogglePVP, HandleTogglePvp},
|
||||
{PacketTypes.TileKill, HandleTileKill},
|
||||
{PacketTypes.PlayerKillMe, HandlePlayerKillMe},
|
||||
{PacketTypes.LiquidSet, HandleLiquidSet},
|
||||
};
|
||||
}
|
||||
|
||||
public static bool HandlerGetData(PacketTypes type, TSPlayer player, MemoryStream data)
|
||||
{
|
||||
GetDataHandlerDelegate handler;
|
||||
if (GetDataHandlerDelegates.TryGetValue(type, out handler))
|
||||
{
|
||||
try
|
||||
{
|
||||
return handler(new GetDataHandlerArgs(player, data));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandlePlayerInfo(GetDataHandlerArgs args)
|
||||
{
|
||||
byte playerid = args.Data.ReadInt8();
|
||||
byte hair = args.Data.ReadInt8();
|
||||
Color hairColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
|
||||
Color skinColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
|
||||
Color eyeColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
|
||||
Color shirtColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
|
||||
Color underShirtColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
|
||||
Color pantsColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
|
||||
Color shoeColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
|
||||
string name = Encoding.ASCII.GetString(args.Data.ReadBytes((int) (args.Data.Length - args.Data.Position - 1)));
|
||||
|
||||
if (hair >= Main.maxHair)
|
||||
{
|
||||
Tools.ForceKick(args.Player, "Hair crash exploit.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name.Length > 32)
|
||||
{
|
||||
Tools.ForceKick(args.Player, "Name exceeded 32 characters.");
|
||||
return true;
|
||||
}
|
||||
if (name.Trim().Length == 0)
|
||||
{
|
||||
Tools.ForceKick(args.Player, "Empty Name.");
|
||||
return true;
|
||||
}
|
||||
var ban = TShock.Bans.GetBanByName(name);
|
||||
if (ban != null)
|
||||
{
|
||||
Tools.ForceKick(args.Player, string.Format("You are banned: {0}", ban.Reason));
|
||||
return true;
|
||||
}
|
||||
if (args.Player.ReceivedInfo)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "Sent client info more than once");
|
||||
}
|
||||
|
||||
args.Player.ReceivedInfo = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleSendTileSquare(GetDataHandlerArgs args)
|
||||
{
|
||||
short size = args.Data.ReadInt16();
|
||||
int x = args.Data.ReadInt32();
|
||||
int y = args.Data.ReadInt32();
|
||||
int plyX = Math.Abs(args.Player.TileX);
|
||||
int plyY = Math.Abs(args.Player.TileY);
|
||||
int tileX = Math.Abs(x);
|
||||
int tileY = Math.Abs(y);
|
||||
if (size > 5 || (ConfigurationManager.RangeChecks && (Math.Abs(plyX - tileX) > 32 || Math.Abs(plyY - tileY) > 32)))
|
||||
{
|
||||
Log.Debug(string.Format("SendTileSquare(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Size:{6})",
|
||||
plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), size));
|
||||
return Tools.HandleGriefer(args.Player, "Send Tile Square Abuse");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleTile(GetDataHandlerArgs args)
|
||||
{
|
||||
byte type = args.Data.ReadInt8();
|
||||
int x = args.Data.ReadInt32();
|
||||
int y = args.Data.ReadInt32();
|
||||
byte tiletype = args.Data.ReadInt8();
|
||||
if (type == 1 || type == 3)
|
||||
{
|
||||
int plyX = Math.Abs(args.Player.TileX);
|
||||
int plyY = Math.Abs(args.Player.TileY);
|
||||
int tileX = Math.Abs(x);
|
||||
int tileY = Math.Abs(y);
|
||||
|
||||
if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32)))
|
||||
{
|
||||
Log.Debug(string.Format("TilePlaced(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Type:{6})",
|
||||
plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), tiletype));
|
||||
return Tools.HandleGriefer(args.Player, "Placing impossible to place blocks.");
|
||||
}
|
||||
}
|
||||
if (ConfigurationManager.DisableBuild)
|
||||
{
|
||||
if (!args.Player.Group.HasPermission("editspawn"))
|
||||
{
|
||||
args.Player.SendMessage("World protected from changes.", Color.Red);
|
||||
TShock.SendTileSquare(args.Player, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (ConfigurationManager.SpawnProtect)
|
||||
{
|
||||
if (!args.Player.Group.HasPermission("editspawn"))
|
||||
{
|
||||
var flag = TShock.CheckSpawn(x, y);
|
||||
if (flag)
|
||||
{
|
||||
args.Player.SendMessage("Spawn protected from changes.", Color.Red);
|
||||
TShock.SendTileSquare(args.Player, x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == 0 && BlacklistTiles[Main.tile[x, y].type] && args.Player.Active)
|
||||
{
|
||||
args.Player.TileThreshold++;
|
||||
var coords = new Vector2(x, y);
|
||||
if (!args.Player.TilesDestroyed.ContainsKey(coords))
|
||||
args.Player.TilesDestroyed.Add(coords, Main.tile[x, y]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleTogglePvp(GetDataHandlerArgs args)
|
||||
{
|
||||
int id = args.Data.ReadByte();
|
||||
bool pvp = args.Data.ReadBoolean();
|
||||
|
||||
args.TPlayer.hostile = pvp;
|
||||
if (id != args.Player.Index)
|
||||
args.TPlayer.hostile = true;
|
||||
if (ConfigurationManager.PermaPvp)
|
||||
args.TPlayer.hostile = true;
|
||||
NetMessage.SendData(30, -1, -1, "", args.Player.Index);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool HandleSendSection(GetDataHandlerArgs args)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "SendSection abuse.");
|
||||
}
|
||||
|
||||
private static bool HandleNpcUpdate(GetDataHandlerArgs args)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "Spawn NPC abuse");
|
||||
}
|
||||
|
||||
private static bool HandlePlayerUpdate(GetDataHandlerArgs args)
|
||||
{
|
||||
byte plr = args.Data.ReadInt8();
|
||||
byte control = args.Data.ReadInt8();
|
||||
byte item = args.Data.ReadInt8();
|
||||
float posx = args.Data.ReadSingle();
|
||||
float posy = args.Data.ReadSingle();
|
||||
float velx = args.Data.ReadSingle();
|
||||
float vely = args.Data.ReadSingle();
|
||||
|
||||
if (Main.verboseNetplay)
|
||||
Debug.WriteLine("Update: {{{0},{1}}} {{{2}, {3}}}", (int)posx, (int)posy, (int)velx, (int)vely);
|
||||
|
||||
if (plr != args.Player.Index)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "Update Player abuse");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleProjectileNew(GetDataHandlerArgs args)
|
||||
{
|
||||
short ident = args.Data.ReadInt16();
|
||||
float posx = args.Data.ReadSingle();
|
||||
float posy = args.Data.ReadSingle();
|
||||
float velx = args.Data.ReadSingle();
|
||||
float vely = args.Data.ReadSingle();
|
||||
float knockback = args.Data.ReadSingle();
|
||||
short dmg = args.Data.ReadInt16();
|
||||
byte owner = args.Data.ReadInt8();
|
||||
byte type = args.Data.ReadInt8();
|
||||
|
||||
if (type == 29 || type == 28 || type == 37)
|
||||
{
|
||||
Log.Debug(string.Format("Explosive(PlyXY:{0}_{1}, Type:{2})", args.Player.TileX, args.Player.TileY, type));
|
||||
return Tools.HandleExplosivesUser(args.Player, "Throwing an explosive device.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandlePlayerKillMe(GetDataHandlerArgs args)
|
||||
{
|
||||
byte id = args.Data.ReadInt8();
|
||||
byte hitdirection = args.Data.ReadInt8();
|
||||
short dmg = args.Data.ReadInt16();
|
||||
bool pvp = args.Data.ReadBoolean();
|
||||
|
||||
if (id != args.Player.Index)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "Trying to execute KillMe on someone else.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandlePlayerDamage(GetDataHandlerArgs args)
|
||||
{
|
||||
byte playerid = args.Data.ReadInt8();
|
||||
byte direction = args.Data.ReadInt8();
|
||||
Int16 damage = args.Data.ReadInt16();
|
||||
byte pvp = args.Data.ReadInt8();
|
||||
|
||||
return !TShock.Players[playerid].TPlayer.hostile;
|
||||
}
|
||||
|
||||
private static bool HandleLiquidSet(GetDataHandlerArgs args)
|
||||
{
|
||||
int x = args.Data.ReadInt32();
|
||||
int y = args.Data.ReadInt32();
|
||||
byte liquid = args.Data.ReadInt8();
|
||||
bool lava = args.Data.ReadBoolean();
|
||||
|
||||
//The liquid was picked up.
|
||||
if (liquid == 0)
|
||||
return false;
|
||||
|
||||
int plyX = Math.Abs(args.Player.TileX);
|
||||
int plyY = Math.Abs(args.Player.TileY);
|
||||
int tileX = Math.Abs(x);
|
||||
int tileY = Math.Abs(y);
|
||||
|
||||
bool bucket = false;
|
||||
for (int i = 0; i < 44; i++)
|
||||
{
|
||||
if (args.TPlayer.inventory[i].type >= 205 && args.TPlayer.inventory[i].type <= 207)
|
||||
{
|
||||
bucket = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lava && !args.Player.Group.HasPermission("canlava"))
|
||||
{
|
||||
args.Player.SendMessage("You do not have permission to use lava", Color.Red);
|
||||
Tools.SendLogs(string.Format("{0} tried using lava", args.Player.Name), Color.Red);
|
||||
// TODO need to revert player changes so they are insync with server
|
||||
return true;
|
||||
}
|
||||
if (!lava && !args.Player.Group.HasPermission("canwater"))
|
||||
{
|
||||
args.Player.SendMessage("You do not have permission to use water", Color.Red);
|
||||
Tools.SendLogs(string.Format("{0} tried using water", args.Player.Name), Color.Red);
|
||||
// TODO need to revert player changes so they are insync with server
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!bucket)
|
||||
{
|
||||
Log.Debug(string.Format("{0}(PlyXY:{1}_{2}, TileXY:{3}_{4}, Result:{5}_{6}, Amount:{7})",
|
||||
lava ? "Lava" : "Water", plyX, plyY, tileX, tileY,
|
||||
Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid));
|
||||
return Tools.HandleGriefer(args.Player, "Manipulating liquid without bucket."); ;
|
||||
}
|
||||
if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32)))
|
||||
{
|
||||
Log.Debug(string.Format("Liquid(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Amount:{6})",
|
||||
plyX, plyY,
|
||||
tileX, tileY,
|
||||
Math.Abs(plyX - tileX), Math.Abs(plyY - tileY),
|
||||
liquid
|
||||
));
|
||||
return Tools.HandleGriefer(args.Player, "Placing impossible to place liquid."); ;
|
||||
}
|
||||
|
||||
if (ConfigurationManager.SpawnProtect)
|
||||
{
|
||||
if (!args.Player.Group.HasPermission("editspawn"))
|
||||
{
|
||||
var flag = TShock.CheckSpawn(x, y);
|
||||
if (flag)
|
||||
{
|
||||
args.Player.SendMessage("The spawn is protected!", Color.Red);
|
||||
// TODO need to revert player changes so they are insync with server
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleTileKill(GetDataHandlerArgs args)
|
||||
{
|
||||
int tilex = args.Data.ReadInt32();
|
||||
int tiley = args.Data.ReadInt32();
|
||||
if (tilex < 0 || tilex >= Main.maxTilesX || tiley < 0 || tiley >= Main.maxTilesY)
|
||||
return false;
|
||||
|
||||
if (Main.tile[tilex, tiley].type != 0x15) //Chest
|
||||
{
|
||||
Log.Debug(string.Format("TileKill(TileXY:{0}_{1}, Type:{2})",
|
||||
tilex, tiley, Main.tile[tilex, tiley].type));
|
||||
Tools.ForceKick(args.Player, string.Format("Tile Kill abuse ({0})", Main.tile[tilex, tiley].type));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011 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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Terraria;
|
||||
using TerrariaAPI;
|
||||
using XNAHelpers;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
public delegate bool GetDataHandlerDelegate(GetDataHandlerArgs args);
|
||||
public class GetDataHandlerArgs : EventArgs
|
||||
{
|
||||
public TSPlayer Player { get; private set; }
|
||||
public MemoryStream Data { get; private set; }
|
||||
|
||||
public Player TPlayer
|
||||
{
|
||||
get { return Player.TPlayer; }
|
||||
}
|
||||
|
||||
public GetDataHandlerArgs(TSPlayer player, MemoryStream data)
|
||||
{
|
||||
Player = player;
|
||||
Data = data;
|
||||
}
|
||||
}
|
||||
public static class GetDataHandlers
|
||||
{
|
||||
private static Dictionary<PacketTypes, GetDataHandlerDelegate> GetDataHandlerDelegates;
|
||||
private static bool[] BlacklistTiles;
|
||||
|
||||
public static void InitGetDataHandler()
|
||||
{
|
||||
#region Blacklisted tiles
|
||||
|
||||
BlacklistTiles = new bool[Main.maxTileSets];
|
||||
BlacklistTiles[0] = true;
|
||||
BlacklistTiles[1] = true;
|
||||
BlacklistTiles[2] = true;
|
||||
BlacklistTiles[6] = true;
|
||||
BlacklistTiles[7] = true;
|
||||
BlacklistTiles[8] = true;
|
||||
BlacklistTiles[9] = true;
|
||||
BlacklistTiles[22] = true;
|
||||
BlacklistTiles[23] = true;
|
||||
BlacklistTiles[25] = true;
|
||||
BlacklistTiles[30] = true;
|
||||
BlacklistTiles[37] = true;
|
||||
BlacklistTiles[38] = true;
|
||||
BlacklistTiles[39] = true;
|
||||
BlacklistTiles[40] = true;
|
||||
BlacklistTiles[41] = true;
|
||||
BlacklistTiles[43] = true;
|
||||
BlacklistTiles[44] = true;
|
||||
BlacklistTiles[45] = true;
|
||||
BlacklistTiles[46] = true;
|
||||
BlacklistTiles[47] = true;
|
||||
BlacklistTiles[53] = true;
|
||||
BlacklistTiles[54] = true;
|
||||
BlacklistTiles[56] = true;
|
||||
BlacklistTiles[57] = true;
|
||||
BlacklistTiles[58] = true;
|
||||
BlacklistTiles[59] = true;
|
||||
BlacklistTiles[60] = true;
|
||||
BlacklistTiles[63] = true;
|
||||
BlacklistTiles[64] = true;
|
||||
BlacklistTiles[65] = true;
|
||||
BlacklistTiles[66] = true;
|
||||
BlacklistTiles[67] = true;
|
||||
BlacklistTiles[68] = true;
|
||||
BlacklistTiles[70] = true;
|
||||
BlacklistTiles[75] = true;
|
||||
BlacklistTiles[76] = true;
|
||||
|
||||
#endregion Blacklisted tiles
|
||||
|
||||
GetDataHandlerDelegates = new Dictionary<PacketTypes, GetDataHandlerDelegate>
|
||||
{
|
||||
{PacketTypes.PlayerInfo, HandlePlayerInfo},
|
||||
{PacketTypes.TileSendSection, HandleSendSection},
|
||||
{PacketTypes.PlayerUpdate, HandlePlayerUpdate},
|
||||
{PacketTypes.Tile, HandleTile},
|
||||
{PacketTypes.TileSendSquare, HandleSendTileSquare},
|
||||
{PacketTypes.NPCUpdate, HandleNpcUpdate},
|
||||
{PacketTypes.PlayerDamage, HandlePlayerDamage},
|
||||
{PacketTypes.ProjectileNew, HandleProjectileNew},
|
||||
{PacketTypes.TogglePVP, HandleTogglePvp},
|
||||
{PacketTypes.TileKill, HandleTileKill},
|
||||
{PacketTypes.PlayerKillMe, HandlePlayerKillMe},
|
||||
{PacketTypes.LiquidSet, HandleLiquidSet},
|
||||
{PacketTypes.PlayerSpawn, HandleSpawn},
|
||||
};
|
||||
}
|
||||
|
||||
public static bool HandlerGetData(PacketTypes type, TSPlayer player, MemoryStream data)
|
||||
{
|
||||
GetDataHandlerDelegate handler;
|
||||
if (GetDataHandlerDelegates.TryGetValue(type, out handler))
|
||||
{
|
||||
try
|
||||
{
|
||||
return handler(new GetDataHandlerArgs(player, data));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandlePlayerInfo(GetDataHandlerArgs args)
|
||||
{
|
||||
byte playerid = args.Data.ReadInt8();
|
||||
byte hair = args.Data.ReadInt8();
|
||||
//Various colours here
|
||||
|
||||
args.Data.Position += 21;
|
||||
bool hardcore = args.Data.ReadBoolean();
|
||||
string name = Encoding.ASCII.GetString(args.Data.ReadBytes((int)(args.Data.Length - args.Data.Position - 1)));
|
||||
|
||||
if (hair >= Main.maxHair)
|
||||
{
|
||||
Tools.ForceKick(args.Player, "Hair crash exploit.");
|
||||
return true;
|
||||
}
|
||||
if (name.Length > 32)
|
||||
{
|
||||
Tools.ForceKick(args.Player, "Name exceeded 32 characters.");
|
||||
return true;
|
||||
}
|
||||
if (name.Trim().Length == 0)
|
||||
{
|
||||
Tools.ForceKick(args.Player, "Empty Name.");
|
||||
return true;
|
||||
}
|
||||
var ban = TShock.Bans.GetBanByName(name);
|
||||
if (ban != null)
|
||||
{
|
||||
Tools.ForceKick(args.Player, string.Format("You are banned: {0}", ban.Reason));
|
||||
return true;
|
||||
}
|
||||
if (args.Player.ReceivedInfo)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "Sent client info more than once");
|
||||
}
|
||||
if (ConfigurationManager.HardcoreOnly)
|
||||
if (!hardcore)
|
||||
{
|
||||
Tools.ForceKick(args.Player, "Server is set to hardcore characters only!");
|
||||
return true;
|
||||
}
|
||||
|
||||
args.Player.ReceivedInfo = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleSendTileSquare(GetDataHandlerArgs args)
|
||||
{
|
||||
short size = args.Data.ReadInt16();
|
||||
int x = args.Data.ReadInt32();
|
||||
int y = args.Data.ReadInt32();
|
||||
int plyX = Math.Abs(args.Player.TileX);
|
||||
int plyY = Math.Abs(args.Player.TileY);
|
||||
int tileX = Math.Abs(x);
|
||||
int tileY = Math.Abs(y);
|
||||
if (size > 5 || (ConfigurationManager.RangeChecks && (Math.Abs(plyX - tileX) > 32 || Math.Abs(plyY - tileY) > 32)))
|
||||
{
|
||||
Log.Debug(string.Format("SendTileSquare(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Size:{6})",
|
||||
plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), size));
|
||||
return Tools.HandleGriefer(args.Player, "Send Tile Square Abuse");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleTile(GetDataHandlerArgs args)
|
||||
{
|
||||
byte type = args.Data.ReadInt8();
|
||||
int x = args.Data.ReadInt32();
|
||||
int y = args.Data.ReadInt32();
|
||||
byte tiletype = args.Data.ReadInt8();
|
||||
if (type == 1 || type == 3)
|
||||
{
|
||||
int plyX = Math.Abs(args.Player.TileX);
|
||||
int plyY = Math.Abs(args.Player.TileY);
|
||||
int tileX = Math.Abs(x);
|
||||
int tileY = Math.Abs(y);
|
||||
|
||||
if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32)))
|
||||
{
|
||||
if (!(type == 1 && ((tiletype == 0 && args.Player.TPlayer.selectedItem == 114) || (tiletype == 53 && args.Player.TPlayer.selectedItem == 266))))
|
||||
{
|
||||
Log.Debug(string.Format("TilePlaced(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Type:{6})",
|
||||
plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), tiletype));
|
||||
return Tools.HandleGriefer(args.Player, "Placing impossible to place blocks.");
|
||||
}
|
||||
}
|
||||
if (tiletype == 48 && !args.Player.Group.HasPermission("canspike"))
|
||||
{
|
||||
args.Player.SendMessage("You do not have permission to place spikes.", Color.Red);
|
||||
Tools.SendLogs(string.Format("{0} tried to place spikes", args.Player.Name), Color.Red);
|
||||
args.Player.SendTileSquare(x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!args.Player.Group.HasPermission("editspawn") && RegionManager.InProtectedArea(x, y, Tools.GetPlayerIP(args.Player.Name)))
|
||||
{
|
||||
args.Player.SendMessage("Region protected from changes.", Color.Red);
|
||||
args.Player.SendTileSquare(x, y);
|
||||
return true;
|
||||
}
|
||||
if (ConfigurationManager.DisableBuild)
|
||||
{
|
||||
if (!args.Player.Group.HasPermission("editspawn"))
|
||||
{
|
||||
args.Player.SendMessage("World protected from changes.", Color.Red);
|
||||
args.Player.SendTileSquare(x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (ConfigurationManager.SpawnProtect)
|
||||
{
|
||||
if (!args.Player.Group.HasPermission("editspawn"))
|
||||
{
|
||||
var flag = TShock.CheckSpawn(x, y);
|
||||
if (flag)
|
||||
{
|
||||
args.Player.SendMessage("Spawn protected from changes.", Color.Red);
|
||||
args.Player.SendTileSquare(x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == 0 && BlacklistTiles[Main.tile[x, y].type] && args.Player.Active)
|
||||
{
|
||||
args.Player.TileThreshold++;
|
||||
var coords = new Vector2(x, y);
|
||||
if (!args.Player.TilesDestroyed.ContainsKey(coords))
|
||||
args.Player.TilesDestroyed.Add(coords, Main.tile[x, y]);
|
||||
}
|
||||
if (args.Player.LastExplosive != null)
|
||||
if ((DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds < 1000)
|
||||
{
|
||||
args.Player.SendMessage("Please wait another " + (1000 - (DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds).ToString() + " milliseconds before placing/destroying tiles", Color.Red);
|
||||
args.Player.SendTileSquare(x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleTogglePvp(GetDataHandlerArgs args)
|
||||
{
|
||||
int id = args.Data.ReadByte();
|
||||
bool pvp = args.Data.ReadBoolean();
|
||||
|
||||
long seconds = (long)(DateTime.UtcNow - args.Player.LastPvpChange).TotalSeconds;
|
||||
if (ConfigurationManager.PvpThrottle > 0 && seconds < ConfigurationManager.PvpThrottle)
|
||||
{
|
||||
args.Player.SendMessage(string.Format("You cannot change pvp status for {0} seconds", ConfigurationManager.PvpThrottle - seconds), 255, 0, 0);
|
||||
args.Player.SetPvP(id != args.Player.Index || ConfigurationManager.PermaPvp ? true : args.TPlayer.hostile);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Player.SetPvP(id != args.Player.Index || ConfigurationManager.PermaPvp ? true : pvp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool HandleSendSection(GetDataHandlerArgs args)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "SendSection abuse.");
|
||||
}
|
||||
|
||||
private static bool HandleNpcUpdate(GetDataHandlerArgs args)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "Spawn NPC abuse");
|
||||
}
|
||||
|
||||
private static bool HandlePlayerUpdate(GetDataHandlerArgs args)
|
||||
{
|
||||
byte plr = args.Data.ReadInt8();
|
||||
byte control = args.Data.ReadInt8();
|
||||
byte item = args.Data.ReadInt8();
|
||||
float posx = args.Data.ReadSingle();
|
||||
float posy = args.Data.ReadSingle();
|
||||
float velx = args.Data.ReadSingle();
|
||||
float vely = args.Data.ReadSingle();
|
||||
|
||||
if (Main.verboseNetplay)
|
||||
Debug.WriteLine("Update: {{{0},{1}}} {{{2}, {3}}}", (int)posx, (int)posy, (int)velx, (int)vely);
|
||||
|
||||
if (plr != args.Player.Index)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "Update Player abuse");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleProjectileNew(GetDataHandlerArgs args)
|
||||
{
|
||||
short ident = args.Data.ReadInt16();
|
||||
float posx = args.Data.ReadSingle();
|
||||
float posy = args.Data.ReadSingle();
|
||||
float velx = args.Data.ReadSingle();
|
||||
float vely = args.Data.ReadSingle();
|
||||
float knockback = args.Data.ReadSingle();
|
||||
short dmg = args.Data.ReadInt16();
|
||||
byte owner = args.Data.ReadInt8();
|
||||
byte type = args.Data.ReadInt8();
|
||||
|
||||
if (type == 29 || type == 28 || type == 37)
|
||||
{
|
||||
Log.Debug(string.Format("Explosive(PlyXY:{0}_{1}, Type:{2})", args.Player.TileX, args.Player.TileY, type));
|
||||
if (ConfigurationManager.DisableBoom && (!args.Player.Group.HasPermission("useexplosives") || !args.Player.Group.HasPermission("ignoregriefdetection")))
|
||||
{
|
||||
Main.projectile[ident].type = 0;
|
||||
args.Player.SendData(PacketTypes.ProjectileNew, "", ident);
|
||||
args.Player.SendMessage("Explosives are disabled!", Color.Red);
|
||||
args.Player.LastExplosive = DateTime.UtcNow;
|
||||
//return true;
|
||||
}
|
||||
else
|
||||
return Tools.HandleExplosivesUser(args.Player, "Throwing an explosive device.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandlePlayerKillMe(GetDataHandlerArgs args)
|
||||
{
|
||||
byte id = args.Data.ReadInt8();
|
||||
if (id != args.Player.Index)
|
||||
{
|
||||
return Tools.HandleGriefer(args.Player, "Trying to execute KillMe on someone else.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandlePlayerDamage(GetDataHandlerArgs args)
|
||||
{
|
||||
byte playerid = args.Data.ReadInt8();
|
||||
return !TShock.Players[playerid].TPlayer.hostile;
|
||||
}
|
||||
|
||||
private static bool HandleLiquidSet(GetDataHandlerArgs args)
|
||||
{
|
||||
int x = args.Data.ReadInt32();
|
||||
int y = args.Data.ReadInt32();
|
||||
byte liquid = args.Data.ReadInt8();
|
||||
bool lava = args.Data.ReadBoolean();
|
||||
|
||||
//The liquid was picked up.
|
||||
if (liquid == 0)
|
||||
return false;
|
||||
|
||||
int plyX = Math.Abs(args.Player.TileX);
|
||||
int plyY = Math.Abs(args.Player.TileY);
|
||||
int tileX = Math.Abs(x);
|
||||
int tileY = Math.Abs(y);
|
||||
|
||||
bool bucket = false;
|
||||
for (int i = 0; i < 44; i++)
|
||||
{
|
||||
if (args.TPlayer.inventory[i].type >= 205 && args.TPlayer.inventory[i].type <= 207)
|
||||
{
|
||||
bucket = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lava && !args.Player.Group.HasPermission("canlava"))
|
||||
{
|
||||
args.Player.SendMessage("You do not have permission to use lava", Color.Red);
|
||||
Tools.SendLogs(string.Format("{0} tried using lava", args.Player.Name), Color.Red);
|
||||
args.Player.SendTileSquare(x, y);
|
||||
return true;
|
||||
}
|
||||
if (!lava && !args.Player.Group.HasPermission("canwater"))
|
||||
{
|
||||
args.Player.SendMessage("You do not have permission to use water", Color.Red);
|
||||
Tools.SendLogs(string.Format("{0} tried using water", args.Player.Name), Color.Red);
|
||||
args.Player.SendTileSquare(x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!bucket)
|
||||
{
|
||||
Log.Debug(string.Format("{0}(PlyXY:{1}_{2}, TileXY:{3}_{4}, Result:{5}_{6}, Amount:{7})",
|
||||
lava ? "Lava" : "Water", plyX, plyY, tileX, tileY,
|
||||
Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid));
|
||||
return Tools.HandleGriefer(args.Player, "Manipulating liquid without bucket."); ;
|
||||
}
|
||||
if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32)))
|
||||
{
|
||||
Log.Debug(string.Format("Liquid(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Amount:{6})",
|
||||
plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid));
|
||||
return Tools.HandleGriefer(args.Player, "Placing impossible to place liquid."); ;
|
||||
}
|
||||
|
||||
if (ConfigurationManager.SpawnProtect)
|
||||
{
|
||||
if (!args.Player.Group.HasPermission("editspawn"))
|
||||
{
|
||||
var flag = TShock.CheckSpawn(x, y);
|
||||
if (flag)
|
||||
{
|
||||
args.Player.SendMessage("The spawn is protected!", Color.Red);
|
||||
args.Player.SendTileSquare(x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleTileKill(GetDataHandlerArgs args)
|
||||
{
|
||||
int tilex = args.Data.ReadInt32();
|
||||
int tiley = args.Data.ReadInt32();
|
||||
if (tilex < 0 || tilex >= Main.maxTilesX || tiley < 0 || tiley >= Main.maxTilesY)
|
||||
return false;
|
||||
|
||||
if (Main.tile[tilex, tiley].type != 0x15) //Chest
|
||||
{
|
||||
Log.Debug(string.Format("TileKill(TileXY:{0}_{1}, Type:{2})",
|
||||
tilex, tiley, Main.tile[tilex, tiley].type));
|
||||
Tools.ForceKick(args.Player, string.Format("Tile Kill abuse ({0})", Main.tile[tilex, tiley].type));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HandleSpawn(GetDataHandlerArgs args)
|
||||
{
|
||||
byte player = args.Data.ReadInt8();
|
||||
int spawnx = args.Data.ReadInt32();
|
||||
int spawny = args.Data.ReadInt32();
|
||||
|
||||
if (args.Player.InitSpawn)
|
||||
{
|
||||
if (ConfigurationManager.HardcoreOnly && (ConfigurationManager.KickOnHardcoreDeath || ConfigurationManager.BanOnHardcoreDeath))
|
||||
if (args.TPlayer.selectedItem != 50)
|
||||
{
|
||||
if (ConfigurationManager.BanOnHardcoreDeath)
|
||||
{
|
||||
if (!Tools.Ban(args.Player, "Death results in a ban"))
|
||||
Tools.ForceKick(args.Player, "Death results in a ban, but can't ban you");
|
||||
}
|
||||
else
|
||||
Tools.ForceKick(args.Player, "Death results in a kick");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
args.Player.InitSpawn = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
76
TShockAPI/ItemManager.cs
Normal file
76
TShockAPI/ItemManager.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Terraria;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
class ItemManager
|
||||
{
|
||||
public static List<ItemBan> BannedItems = new List<ItemBan>();
|
||||
|
||||
public static void LoadBans()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(FileTools.ItemBansPath))
|
||||
return;
|
||||
|
||||
BannedItems.Clear();
|
||||
|
||||
foreach (var line in File.ReadAllLines(FileTools.ItemBansPath))
|
||||
{
|
||||
int ID = -1;
|
||||
if (Int32.TryParse(line, out ID))
|
||||
{
|
||||
if (ID < Main.maxItemTypes && ID > 0)
|
||||
{
|
||||
var item = Tools.GetItemById(ID);
|
||||
BannedItems.Add(new ItemBan(ID, item.name));
|
||||
Log.Info("Item: " + item.name + " is banned");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warn("Invalid ID " + ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ItemIsBanned(string ID)
|
||||
{
|
||||
foreach (ItemBan item in BannedItems)
|
||||
{
|
||||
if (ID == item.Name)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class ItemBan
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public ItemBan(int id, string name)
|
||||
{
|
||||
ID = id;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public ItemBan()
|
||||
{
|
||||
ID = -1;
|
||||
Name = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,24 +53,6 @@ namespace TShockAPI
|
|||
_logWriter = new StreamWriter(filename, !clear);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which writes a message directly to the log file.
|
||||
/// </summary>
|
||||
private static void Write(String message, LogLevel level)
|
||||
{
|
||||
if (!MayWriteType(level))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string caller = "TShock";
|
||||
|
||||
_logWriter.WriteLine(string.Format("{0} - {1}: {2}: {3}",
|
||||
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
|
||||
caller, level.ToString().ToUpper(), message));
|
||||
_logWriter.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the log level contains the specified flag.
|
||||
/// </summary>
|
||||
|
|
@ -116,6 +98,16 @@ namespace TShockAPI
|
|||
Write(message, LogLevel.Info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an informative string to the log file. Also outputs to the console.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to be written.</param>
|
||||
public static void ConsoleInfo(String message)
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
Write(message, LogLevel.Info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a debug string to the log file.
|
||||
/// </summary>
|
||||
|
|
@ -124,5 +116,31 @@ namespace TShockAPI
|
|||
{
|
||||
Write(message, LogLevel.Debug);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which writes a message directly to the log file.
|
||||
/// </summary>
|
||||
private static void Write(String message, LogLevel level)
|
||||
{
|
||||
if (!MayWriteType(level))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string caller = "TShock";
|
||||
|
||||
StackFrame frame = new StackTrace().GetFrame(2);
|
||||
if (frame != null)
|
||||
{
|
||||
var meth = frame.GetMethod();
|
||||
if (meth != null)
|
||||
caller = meth.DeclaringType.Name;
|
||||
}
|
||||
|
||||
_logWriter.WriteLine(string.Format("{0} - {1}: {2}: {3}",
|
||||
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
|
||||
caller, level.ToString().ToUpper(), message));
|
||||
_logWriter.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
|
|||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyVersion("2.3.0.0627")]
|
||||
[assembly: AssemblyFileVersion("2.3.0.0627")]
|
||||
307
TShockAPI/RegionManager.cs
Normal file
307
TShockAPI/RegionManager.cs
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Terraria;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
public class RegionManager
|
||||
{
|
||||
public static List<Region> Regions = new List<Region>();
|
||||
|
||||
public static bool AddRegion(int tx, int ty, int width, int height, string regionname, string worldname)
|
||||
{
|
||||
foreach (Region nametest in Regions)
|
||||
{
|
||||
if (regionname.ToLower() == nametest.RegionName.ToLower())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Regions.Add(new Region(new Rectangle(tx, ty, width, height), regionname, true, worldname));
|
||||
WriteSettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool AddNewUser(string regionName, string IP)
|
||||
{
|
||||
foreach (Region nametest in Regions)
|
||||
{
|
||||
if (regionName.ToLower() == nametest.RegionName.ToLower())
|
||||
{
|
||||
nametest.RegionAllowedIPs.Add(IP.ToLower());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool DeleteRegion(string name)
|
||||
{
|
||||
foreach (Region nametest in Regions)
|
||||
{
|
||||
if (name.ToLower() == nametest.RegionName.ToLower() && nametest.WorldRegionName == Main.worldName)
|
||||
{
|
||||
Regions.Remove(nametest);
|
||||
WriteSettings();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool SetRegionState(string name, bool state)
|
||||
{
|
||||
foreach (Region nametest in Regions)
|
||||
{
|
||||
if (name.ToLower() == nametest.RegionName.ToLower())
|
||||
{
|
||||
nametest.DisableBuild = state;
|
||||
WriteSettings();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool InProtectedArea(int X, int Y, string IP)
|
||||
{
|
||||
foreach(Region region in Regions)
|
||||
{
|
||||
if (X >= region.RegionArea.Left && X <= region.RegionArea.Right && Y >= region.RegionArea.Top && Y <= region.RegionArea.Bottom && region.DisableBuild && Main.worldName == region.WorldRegionName && (!AllowedUser(region.RegionName, IP.ToLower()) || region.RegionAllowedIPs.Count == 0))
|
||||
{
|
||||
Console.WriteLine(region.RegionName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int GetRegionIndex(string regionName)
|
||||
{
|
||||
for(int i = 0; i< Regions.Count;i++)
|
||||
{
|
||||
if(Regions[i].RegionName == regionName)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static bool AllowedUser(string regionName, string playerIP)
|
||||
{
|
||||
int ID = -1;
|
||||
if ((ID = GetRegionIndex(regionName)) != -1)
|
||||
{
|
||||
for (int i = 0; i < Regions[ID].RegionAllowedIPs.Count; i++)
|
||||
{
|
||||
if (Regions[ID].RegionAllowedIPs[i].ToLower() == playerIP.ToLower())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void WriteSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
|
||||
xmlWriterSettings.Indent = true;
|
||||
xmlWriterSettings.NewLineChars = Environment.NewLine;
|
||||
|
||||
using (XmlWriter settingsw = XmlWriter.Create(FileTools.RegionsPath, xmlWriterSettings))
|
||||
{
|
||||
settingsw.WriteStartDocument();
|
||||
settingsw.WriteStartElement("Regions");
|
||||
|
||||
foreach (Region region in Regions)
|
||||
{
|
||||
settingsw.WriteStartElement("ProtectedRegion");
|
||||
settingsw.WriteElementString("RegionName", region.RegionName);
|
||||
settingsw.WriteElementString("Point1X", region.RegionArea.X.ToString());
|
||||
settingsw.WriteElementString("Point1Y", region.RegionArea.Y.ToString());
|
||||
settingsw.WriteElementString("Point2X", region.RegionArea.Width.ToString());
|
||||
settingsw.WriteElementString("Point2Y", region.RegionArea.Height.ToString());
|
||||
settingsw.WriteElementString("Protected", region.DisableBuild.ToString());
|
||||
settingsw.WriteElementString("WorldName", region.WorldRegionName);
|
||||
|
||||
settingsw.WriteElementString("AllowedUserCount", region.RegionAllowedIPs.Count.ToString());
|
||||
for (int i = 0; i < region.RegionAllowedIPs.Count; i++)
|
||||
{
|
||||
settingsw.WriteElementString("IP", region.RegionAllowedIPs[i]);
|
||||
}
|
||||
|
||||
settingsw.WriteEndElement();
|
||||
}
|
||||
|
||||
settingsw.WriteEndElement();
|
||||
settingsw.WriteEndDocument();
|
||||
}
|
||||
Log.Info("Wrote Regions");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Warn("Could not write Regions");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReadAllSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
|
||||
xmlReaderSettings.IgnoreWhitespace = true;
|
||||
|
||||
using (XmlReader settingr = XmlReader.Create(FileTools.RegionsPath, xmlReaderSettings))
|
||||
{
|
||||
while (settingr.Read())
|
||||
{
|
||||
if (settingr.IsStartElement())
|
||||
{
|
||||
switch (settingr.Name)
|
||||
{
|
||||
case "Regions":
|
||||
{
|
||||
break;
|
||||
}
|
||||
case "ProtectedRegion":
|
||||
{
|
||||
if (settingr.Read())
|
||||
{
|
||||
string name = null;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
bool state = true;
|
||||
string worldname = null;
|
||||
int playercount = 0;
|
||||
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
name = settingr.Value;
|
||||
else
|
||||
Log.Warn("Region name is empty");
|
||||
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
Int32.TryParse(settingr.Value, out x);
|
||||
else
|
||||
Log.Warn("x for region " + name + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
Int32.TryParse(settingr.Value, out y);
|
||||
else
|
||||
Log.Warn("y for region " + name + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
Int32.TryParse(settingr.Value, out width);
|
||||
else
|
||||
Log.Warn("Width for region " + name + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
Int32.TryParse(settingr.Value, out height);
|
||||
else
|
||||
Log.Warn("Height for region " + name + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
bool.TryParse(settingr.Value, out state);
|
||||
else
|
||||
Log.Warn("State for region " + name + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
worldname = settingr.Value;
|
||||
else
|
||||
Log.Warn("Worldname for region " + name + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
Int32.TryParse(settingr.Value, out playercount);
|
||||
else
|
||||
Log.Warn("Playercount for region " + name + " is empty");
|
||||
|
||||
AddRegion(x, y, width, height, name, worldname);
|
||||
|
||||
if (playercount > 0)
|
||||
{
|
||||
for (int i = 0; i < playercount; i++)
|
||||
{
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
{
|
||||
int ID = RegionManager.GetRegionIndex(name);
|
||||
Regions[ID].RegionAllowedIPs.Add(settingr.Value);
|
||||
}
|
||||
else
|
||||
Log.Warn("PlayerIP " + i + " for region " + name + " is empty");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.Info("Read Regions");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Warn("Could not read Regions");
|
||||
WriteSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Region
|
||||
{
|
||||
public Rectangle RegionArea { get; set; }
|
||||
public string RegionName { get; set; }
|
||||
public bool DisableBuild { get; set; }
|
||||
public string WorldRegionName { get; set; }
|
||||
public List<string> RegionAllowedIPs = new List<string>();
|
||||
|
||||
public Region(Rectangle region, string name, bool disablebuild, string worldname)
|
||||
{
|
||||
RegionArea = region;
|
||||
RegionName = name;
|
||||
DisableBuild = disablebuild;
|
||||
WorldRegionName = worldname;
|
||||
}
|
||||
|
||||
public Region()
|
||||
{
|
||||
RegionArea = Rectangle.Empty;
|
||||
RegionName = string.Empty;
|
||||
DisableBuild = true;
|
||||
WorldRegionName = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
136
TShockAPI/RememberPosManager.cs
Normal file
136
TShockAPI/RememberPosManager.cs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Terraria;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Xml;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
class RemeberedPosManager
|
||||
{
|
||||
public static List<RemeberedPos> RemeberedPosistions = new List<RemeberedPos>();
|
||||
|
||||
public static void LoadPos()
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
|
||||
xmlReaderSettings.IgnoreWhitespace = true;
|
||||
|
||||
using (XmlReader settingr = XmlReader.Create(FileTools.RememberedPosPath, xmlReaderSettings))
|
||||
{
|
||||
while (settingr.Read())
|
||||
{
|
||||
if (settingr.IsStartElement())
|
||||
{
|
||||
switch (settingr.Name)
|
||||
{
|
||||
case "Positions":
|
||||
{
|
||||
break;
|
||||
}
|
||||
case "Player":
|
||||
{
|
||||
if (settingr.Read())
|
||||
{
|
||||
string IP = null;
|
||||
float X = 0;
|
||||
float Y = 0;
|
||||
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
IP = settingr.Value;
|
||||
else
|
||||
Log.Warn("IP is empty");
|
||||
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
float.TryParse(settingr.Value, out X);
|
||||
else
|
||||
Log.Warn("X for IP " + IP + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
float.TryParse(settingr.Value, out Y);
|
||||
else
|
||||
Log.Warn("Y for IP " + IP + " is empty");
|
||||
|
||||
if (X != 0 && Y != 0)
|
||||
RemeberedPosistions.Add(new RemeberedPos(IP, new Vector2(X, Y)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.Info("Read Remembered Positions");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Warn("Could not read Remembered Positions");
|
||||
WriteSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
|
||||
xmlWriterSettings.Indent = true;
|
||||
xmlWriterSettings.NewLineChars = Environment.NewLine;
|
||||
|
||||
using (XmlWriter settingsw = XmlWriter.Create(FileTools.RememberedPosPath, xmlWriterSettings))
|
||||
{
|
||||
settingsw.WriteStartDocument();
|
||||
settingsw.WriteStartElement("Positions");
|
||||
|
||||
foreach (RemeberedPos player in RemeberedPosistions)
|
||||
{
|
||||
settingsw.WriteStartElement("Player");
|
||||
settingsw.WriteElementString("IP", player.IP);
|
||||
settingsw.WriteElementString("X", player.Pos.X.ToString());
|
||||
settingsw.WriteElementString("Y", player.Pos.Y.ToString());
|
||||
settingsw.WriteEndElement();
|
||||
}
|
||||
|
||||
settingsw.WriteEndElement();
|
||||
settingsw.WriteEndDocument();
|
||||
}
|
||||
Log.Info("Wrote Remembered Positions");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Warn("Could not write Remembered Positions");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class RemeberedPos
|
||||
{
|
||||
public string IP { get; set; }
|
||||
public Vector2 Pos { get; set; }
|
||||
|
||||
public RemeberedPos(string ip, Vector2 pos)
|
||||
{
|
||||
IP = ip;
|
||||
Pos = pos;
|
||||
}
|
||||
|
||||
public RemeberedPos()
|
||||
{
|
||||
IP = string.Empty;
|
||||
Pos = Vector2.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
TShockAPI/Resources.Designer.cs
generated
18
TShockAPI/Resources.Designer.cs
generated
|
|
@ -1,7 +1,7 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.225
|
||||
// Runtime Version:4.0.30319.1
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
|
|
@ -71,9 +71,9 @@ namespace TShockAPI {
|
|||
///#ALWAYS DECLARE A GROUP'S PARENT BEFORE YOU DECLARE THE GROUP
|
||||
///
|
||||
///#currently avaliable permissions:
|
||||
///#kick ban ignorecheatdetection
|
||||
///#maintenance cfg causeevents spawnboss tp
|
||||
///#spawnmob che [rest of string was truncated]";.
|
||||
///#reservedslot - reserved slot for player
|
||||
///#canwater - allow players to use water
|
||||
///#canlav [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string groups {
|
||||
get {
|
||||
|
|
@ -81,6 +81,16 @@ namespace TShockAPI {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to #see https://github.com/TShock/TShock/wiki/Item-List for a list of groups
|
||||
///#List each banned item below this with spaces.
|
||||
/// </summary>
|
||||
internal static string itembans {
|
||||
get {
|
||||
return ResourceManager.GetString("itembans", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to #format
|
||||
///#ip group
|
||||
|
|
|
|||
|
|
@ -1,21 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011 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/>.
|
||||
-->
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
|
@ -138,6 +121,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
<data name="groups" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>config\groups.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="itembans" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>config\itembans.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="users" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>config\users.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
|
|
|
|||
BIN
TShockAPI/SqlBins/Community.CsharpSqlite.SQLiteClient.dll
Normal file
BIN
TShockAPI/SqlBins/Community.CsharpSqlite.SQLiteClient.dll
Normal file
Binary file not shown.
BIN
TShockAPI/SqlBins/Community.CsharpSqlite.dll
Normal file
BIN
TShockAPI/SqlBins/Community.CsharpSqlite.dll
Normal file
Binary file not shown.
BIN
TShockAPI/SqlBins/MySql.Data.dll
Normal file
BIN
TShockAPI/SqlBins/MySql.Data.dll
Normal file
Binary file not shown.
BIN
TShockAPI/SqlBins/MySql.Web.dll
Normal file
BIN
TShockAPI/SqlBins/MySql.Web.dll
Normal file
Binary file not shown.
|
|
@ -1,271 +0,0 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011 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.Text;
|
||||
|
||||
namespace StreamBinary
|
||||
{
|
||||
public static class StreamExt
|
||||
{
|
||||
public static void FillBuffer(this Stream stream, byte[] buf, int numBytes)
|
||||
{
|
||||
int read;
|
||||
if (numBytes == 0x1)
|
||||
{
|
||||
read = stream.ReadByte();
|
||||
if (read == -1)
|
||||
{
|
||||
throw new EndOfStreamException("End of stream");
|
||||
}
|
||||
buf[0x0] = (byte)read;
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = 0x0;
|
||||
do
|
||||
{
|
||||
read = stream.Read(buf, offset, numBytes - offset);
|
||||
if (read == 0x0)
|
||||
{
|
||||
throw new EndOfStreamException("End of stream");
|
||||
}
|
||||
offset += read;
|
||||
}
|
||||
while (offset < numBytes);
|
||||
}
|
||||
|
||||
}
|
||||
public static void WriteBoolean(this Stream s, bool num)
|
||||
{
|
||||
s.WriteByte((byte)(num ? 1 : 0));
|
||||
}
|
||||
public static void WriteInt8(this Stream s, byte num)
|
||||
{
|
||||
s.WriteByte(num);
|
||||
}
|
||||
public static void WriteInt16(this Stream s, Int16 num)
|
||||
{
|
||||
s.WriteInt8((byte)(num & 0xff));
|
||||
s.WriteInt8((byte)(num >> 8));
|
||||
}
|
||||
public static void WriteInt32(this Stream s, Int32 num)
|
||||
{
|
||||
s.WriteInt16((Int16)(num & 0xffff));
|
||||
s.WriteInt16((Int16)(num >> 16));
|
||||
}
|
||||
public static void WriteInt64(this Stream s, Int64 num)
|
||||
{
|
||||
s.WriteInt32((Int32)(num & 0xffffffff));
|
||||
s.WriteInt32((Int32)(num >> 32));
|
||||
}
|
||||
public static unsafe void WriteSingle(this Stream s, float num)
|
||||
{
|
||||
Int32 n1 = *((Int32*)&num);
|
||||
s.WriteInt32(n1);
|
||||
}
|
||||
public static unsafe void WriteDouble(this Stream s, double num)
|
||||
{
|
||||
Int64 n1 = *((Int64*)&num);
|
||||
s.WriteInt64(n1);
|
||||
}
|
||||
public static void WriteBytes(this Stream s, byte[] bytes)
|
||||
{
|
||||
s.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
public static void WriteBytesWithLength(this Stream s, byte[] bytes)
|
||||
{
|
||||
s.WriteInt32(bytes.Length);
|
||||
s.WriteBytes(bytes);
|
||||
}
|
||||
public static void WriteBytes(this Stream s, byte[] bytes, Int32 len)
|
||||
{
|
||||
s.Write(bytes, 0, len);
|
||||
}
|
||||
public static void WriteString(this Stream s, string str)
|
||||
{
|
||||
if (str == null)
|
||||
str = string.Empty;
|
||||
|
||||
s.WriteEncodedInt((Int32)str.Length);
|
||||
if (str.Length > 0)
|
||||
s.WriteBytes(Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
public static void WriteEncodedInt(this Stream s, int value)
|
||||
{
|
||||
uint num = (uint)value;
|
||||
while (num >= 0x80)
|
||||
{
|
||||
s.WriteInt8((byte)(num | 0x80));
|
||||
num = num >> 0x7;
|
||||
}
|
||||
s.WriteInt8((byte)num);
|
||||
}
|
||||
|
||||
public static byte ReadInt8(this Stream s)
|
||||
{
|
||||
int read = s.ReadByte();
|
||||
if (read == -1)
|
||||
{
|
||||
throw new EndOfStreamException("End of stream");
|
||||
}
|
||||
return (byte)read;
|
||||
}
|
||||
public static bool ReadBoolean(this Stream s)
|
||||
{
|
||||
return s.ReadInt8() != 0;
|
||||
}
|
||||
|
||||
public static Int16 ReadInt16(this Stream s)
|
||||
{
|
||||
byte n1 = s.ReadInt8();
|
||||
byte n2 = s.ReadInt8();
|
||||
return (Int16)(n1 | (n2 << 8));
|
||||
}
|
||||
public static UInt16 ReadUInt16(this Stream s)
|
||||
{
|
||||
byte n1 = s.ReadInt8();
|
||||
byte n2 = s.ReadInt8();
|
||||
return (UInt16)(n1 | (n2 << 8));
|
||||
}
|
||||
|
||||
public static Int32 ReadInt32(this Stream s)
|
||||
{
|
||||
Int16 n1 = s.ReadInt16();
|
||||
Int16 n2 = s.ReadInt16();
|
||||
return (Int32)(n1 | (n2 << 16));
|
||||
}
|
||||
public static UInt32 ReadUInt32(this Stream s)
|
||||
{
|
||||
UInt16 n1 = s.ReadUInt16();
|
||||
UInt16 n2 = s.ReadUInt16();
|
||||
return (UInt32)(n1 | (n2 << 16));
|
||||
}
|
||||
|
||||
public static Int64 ReadInt64(this Stream s)
|
||||
{
|
||||
Int64 n1 = s.ReadInt32();
|
||||
Int64 n2 = s.ReadInt32();
|
||||
return (Int64)(n1 | (n2 << 32));
|
||||
}
|
||||
public static UInt64 ReadUInt64(this Stream s)
|
||||
{
|
||||
UInt64 n1 = s.ReadUInt32();
|
||||
UInt64 n2 = s.ReadUInt32();
|
||||
return (n1 | (n2 << 32));
|
||||
}
|
||||
public static unsafe float ReadSingle(this Stream s)
|
||||
{
|
||||
var ret = (UInt32)s.ReadUInt32();
|
||||
return *((float*)&ret);
|
||||
}
|
||||
public static unsafe double ReadDouble(this Stream s)
|
||||
{
|
||||
var ret = (UInt64)s.ReadUInt64();
|
||||
return *((double*)&ret);
|
||||
}
|
||||
|
||||
public static byte[] ReadBytes(this Stream s)
|
||||
{
|
||||
Int32 len = s.ReadInt32();
|
||||
return s.ReadBytes(len);
|
||||
}
|
||||
public static byte[] ReadBytes(this Stream s, Int32 len)
|
||||
{
|
||||
byte[] ret = new byte[len];
|
||||
s.FillBuffer(ret, len);
|
||||
return ret;
|
||||
}
|
||||
public static string ReadString(this Stream s)
|
||||
{
|
||||
int len = s.ReadEncodedInt();
|
||||
if (len > 0)
|
||||
return Encoding.UTF8.GetString(s.ReadBytes(len));
|
||||
return string.Empty;
|
||||
}
|
||||
public static int ReadEncodedInt(this Stream s)
|
||||
{
|
||||
byte num3;
|
||||
int num = 0x0;
|
||||
int num2 = 0x0;
|
||||
do
|
||||
{
|
||||
if (num2 == 0x23)
|
||||
{
|
||||
throw new FormatException("Format_Bad7BitInt32");
|
||||
}
|
||||
num3 = s.ReadInt8();
|
||||
num |= (num3 & 0x7f) << num2;
|
||||
num2 += 0x7;
|
||||
}
|
||||
while ((num3 & 0x80) != 0x0);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
public static class MemoryStreamExt
|
||||
{
|
||||
public static void Reset(this MemoryStream ms)
|
||||
{
|
||||
ms.Position = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace StreamBinary.Generic
|
||||
{
|
||||
public static class StreamGenericExt
|
||||
{
|
||||
static Dictionary<Type, Action<Stream, object>> WriteFuncs = new Dictionary<Type, Action<Stream, object>>()
|
||||
{
|
||||
{typeof(bool), (s, o) => s.WriteBoolean((bool)o)},
|
||||
{typeof(byte), (s, o) => s.WriteInt8((byte)o)},
|
||||
{typeof(Int16), (s, o) => s.WriteInt16((Int16)o)},
|
||||
{typeof(Int32), (s, o) => s.WriteInt32((Int32)o)},
|
||||
{typeof(Int64), (s, o) => s.WriteInt64((Int64)o)},
|
||||
{typeof(byte[]), (s, o) => s.WriteBytes((byte[])o)},
|
||||
{typeof(string), (s, o) => s.WriteString((string)o)},
|
||||
};
|
||||
public static void Write<T>(this Stream stream, T obj)
|
||||
{
|
||||
if (WriteFuncs.ContainsKey(typeof(T)))
|
||||
{
|
||||
WriteFuncs[typeof(T)](stream, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
static Dictionary<Type, Func<Stream, object>> ReadFuncs = new Dictionary<Type, Func<Stream, object>>()
|
||||
{
|
||||
{typeof(bool), s => s.ReadBoolean()},
|
||||
{typeof(byte), s => s.ReadInt8()},
|
||||
{typeof(Int16), s => s.ReadInt16()},
|
||||
{typeof(Int32), s => s.ReadInt32()},
|
||||
{typeof(Int64), s => s.ReadInt64()},
|
||||
{typeof(string), s => s.ReadString()},
|
||||
};
|
||||
public static T Read<T>(this Stream stream)
|
||||
{
|
||||
if (ReadFuncs.ContainsKey(typeof(T)))
|
||||
return (T)ReadFuncs[typeof(T)](stream);
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,20 +19,27 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Terraria;
|
||||
using TerrariaAPI;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
public class TSPlayer
|
||||
{
|
||||
public static readonly TSPlayer Server = new ServerPlayer();
|
||||
public static readonly TSServerPlayer Server = new TSServerPlayer();
|
||||
public static readonly TSPlayer All = new TSPlayer("All");
|
||||
public uint TileThreshold { get; set; }
|
||||
public Dictionary<Vector2, Tile> TilesDestroyed { get; set; }
|
||||
public int TileThreshold { get; set; }
|
||||
public Dictionary<Vector2, Tile> TilesDestroyed { get; protected set; }
|
||||
public bool SyncHP { get; set; }
|
||||
public bool SyncMP { get; set; }
|
||||
public Group Group { get; set; }
|
||||
public bool ReceivedInfo { get; set; }
|
||||
public int Index { get; protected set; }
|
||||
public DateTime LastPvpChange { get; protected set; }
|
||||
public Rectangle TempArea = new Rectangle();
|
||||
public DateTime LastExplosive { get; set; }
|
||||
public bool InitSpawn = false;
|
||||
public bool DisplayLogs = true;
|
||||
|
||||
public bool RealPlayer
|
||||
{
|
||||
get { return Index >= 0 && Index < Main.maxNetPlayers; }
|
||||
|
|
@ -41,6 +48,13 @@ namespace TShockAPI
|
|||
{
|
||||
get { return RealPlayer ? Netplay.serverSock[Index].active && !Netplay.serverSock[Index].kill : false; }
|
||||
}
|
||||
public string IP
|
||||
{
|
||||
get
|
||||
{
|
||||
return RealPlayer ? Tools.GetRealIP(Netplay.serverSock[Index].tcpClient.Client.RemoteEndPoint.ToString()) : "";
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Terraria Player
|
||||
/// </summary>
|
||||
|
|
@ -49,13 +63,6 @@ namespace TShockAPI
|
|||
{
|
||||
get { return TPlayer.name; }
|
||||
}
|
||||
public string IP
|
||||
{
|
||||
get
|
||||
{
|
||||
return RealPlayer ? Tools.GetRealIP(Netplay.serverSock[Index].tcpClient.Client.RemoteEndPoint.ToString()) : "";
|
||||
}
|
||||
}
|
||||
public bool Active
|
||||
{
|
||||
get { return TPlayer.active; }
|
||||
|
|
@ -87,6 +94,25 @@ namespace TShockAPI
|
|||
{
|
||||
get { return (int)(Y / 16); }
|
||||
}
|
||||
public bool InventorySlotAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
bool flag = false;
|
||||
if (RealPlayer)
|
||||
{
|
||||
for (int i = 0; i < 40; i++)
|
||||
{
|
||||
if (!TPlayer.inventory[i].active)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
public TSPlayer(int index)
|
||||
{
|
||||
|
|
@ -104,6 +130,62 @@ namespace TShockAPI
|
|||
Group = new Group("null");
|
||||
}
|
||||
|
||||
public virtual void Disconnect(string reason)
|
||||
{
|
||||
SendData(PacketTypes.Disconnect, reason);
|
||||
}
|
||||
|
||||
public bool Teleport(int tileX, int tileY)
|
||||
{
|
||||
this.InitSpawn = false;
|
||||
int spawnTileX = Main.spawnTileX;
|
||||
int spawnTileY = Main.spawnTileY;
|
||||
Main.spawnTileX = tileX;
|
||||
Main.spawnTileY = tileY;
|
||||
SendData(PacketTypes.WorldInfo);
|
||||
SendTileSquare(tileX, tileY, 30);
|
||||
if (TPlayer.SpawnX >= 0 && TPlayer.SpawnY >= 0)
|
||||
{
|
||||
Main.tile[TPlayer.SpawnX, TPlayer.SpawnY].active = false;
|
||||
NetMessage.SendTileSquare(Index, TPlayer.SpawnX, TPlayer.SpawnY, 1);
|
||||
Spawn();
|
||||
Main.tile[TPlayer.SpawnX, TPlayer.SpawnY].active = true;
|
||||
NetMessage.SendTileSquare(Index, TPlayer.SpawnX, TPlayer.SpawnY, 1);
|
||||
SendMessage("Warning! Your bed spawn point has been destroyed because of warp", Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
Spawn();
|
||||
}
|
||||
Main.spawnTileX = spawnTileX;
|
||||
Main.spawnTileY = spawnTileY;
|
||||
SendData(PacketTypes.WorldInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Spawn()
|
||||
{
|
||||
SendData(PacketTypes.PlayerSpawn, "", Index, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public virtual void SendTileSquare(int x, int y, int size = 10)
|
||||
{
|
||||
SendData(PacketTypes.TileSendSquare, "", size, (float)(x - (size / 2)), (float)(y - (size / 2)), 0f);
|
||||
}
|
||||
|
||||
public virtual void GiveItem(int type, string name, int width, int height, int stack)
|
||||
{
|
||||
int itemid = Terraria.Item.NewItem((int)X, (int)Y, width, height, type, stack, true);
|
||||
// This is for special pickaxe/hammers/swords etc
|
||||
Main.item[itemid].SetDefaults(name);
|
||||
// The set default overrides the wet and stack set by NewItem
|
||||
Main.item[itemid].wet = Collision.WetCollision(Main.item[itemid].position, Main.item[itemid].width, Main.item[itemid].height);
|
||||
Main.item[itemid].stack = stack;
|
||||
Main.item[itemid].owner = Index;
|
||||
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 SendMessage(string msg)
|
||||
{
|
||||
SendMessage(msg, 0, 255, 0);
|
||||
|
|
@ -116,30 +198,104 @@ namespace TShockAPI
|
|||
|
||||
public virtual void SendMessage(string msg, byte red, byte green, byte blue)
|
||||
{
|
||||
NetMessage.SendData(0x19, Index, -1, msg, 255, red, green, blue);
|
||||
SendData(PacketTypes.ChatText, msg, 255, red, green, blue);
|
||||
}
|
||||
|
||||
public virtual void DamagePlayer(int damage)
|
||||
{
|
||||
NetMessage.SendData((int)PacketTypes.PlayerDamage, -1, -1, "", Index, ((new Random()).Next(-1, 1)), damage, (float)0);
|
||||
}
|
||||
|
||||
public virtual void SetPvP(bool pvp)
|
||||
{
|
||||
if (TPlayer.hostile != pvp)
|
||||
{
|
||||
LastPvpChange = DateTime.UtcNow;
|
||||
TPlayer.hostile = pvp;
|
||||
All.SendMessage(string.Format("{0} has {1} PvP!", Name, pvp ? "enabled" : "disabled"), Main.teamColor[Team]);
|
||||
}
|
||||
//Broadcast anyways to keep players synced
|
||||
NetMessage.SendData((int)PacketTypes.TogglePVP, -1, -1, "", Index);
|
||||
}
|
||||
|
||||
//Todo: Separate this into a few functions. SendTo, SendToAll, etc
|
||||
public void SendData(PacketTypes msgType, string text = "", int number = 0, float number2 = 0f, float number3 = 0f, float number4 = 0f, int number5 = 0)
|
||||
{
|
||||
if (RealPlayer && !ConnectionAlive)
|
||||
return;
|
||||
NetMessage.SendData((int)msgType, Index, -1, text, number, number2, number3, number4, number5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ServerPlayer : TSPlayer
|
||||
public class TSServerPlayer : TSPlayer
|
||||
{
|
||||
public ServerPlayer() : base("Server")
|
||||
public TSServerPlayer() : base("Server")
|
||||
{
|
||||
Group = new SuperAdminGroup();
|
||||
}
|
||||
|
||||
public override void SendMessage(string msg)
|
||||
{
|
||||
Console.WriteLine(msg);
|
||||
}
|
||||
public override void SendMessage(string msg, byte red, byte green, byte blue)
|
||||
{
|
||||
SendMessage(msg);
|
||||
SendMessage(msg, 0, 255, 0);
|
||||
}
|
||||
|
||||
public override void SendMessage(string msg, Color color)
|
||||
{
|
||||
SendMessage(msg);
|
||||
SendMessage(msg, color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public override void SendMessage(string msg, byte red, byte green, byte blue)
|
||||
{
|
||||
Console.WriteLine(msg);
|
||||
}
|
||||
|
||||
public void SetBloodMoon(bool bloodMoon)
|
||||
{
|
||||
Main.bloodMoon = bloodMoon;
|
||||
SetTime(false, 0);
|
||||
}
|
||||
|
||||
public void SetTime(bool dayTime, double time)
|
||||
{
|
||||
Main.dayTime = dayTime;
|
||||
Main.time = time;
|
||||
NetMessage.SendData((int)PacketTypes.TimeSet, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
|
||||
NetMessage.syncPlayers();
|
||||
}
|
||||
|
||||
public void SpawnNPC(int type, string name, int amount, int startTileX, int startTileY, int tileXRange = 100, int tileYRange = 50)
|
||||
{
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
int spawnTileX;
|
||||
int spawnTileY;
|
||||
Tools.GetRandomClearTileWithInRange(startTileX, startTileY, tileXRange, tileYRange, out spawnTileX, out spawnTileY);
|
||||
int npcid = NPC.NewNPC(spawnTileX * 16, spawnTileY * 16, type, 0);
|
||||
// This is for special slimes
|
||||
Main.npc[npcid].SetDefaults(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void StrikeNPC(int npcid, int damage, float knockBack, int hitDirection)
|
||||
{
|
||||
Main.npc[npcid].StrikeNPC(damage, knockBack, hitDirection);
|
||||
NetMessage.SendData((int)PacketTypes.NPCStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
|
||||
}
|
||||
|
||||
public void RevertKillTile(Dictionary<Vector2, Tile> destroyedTiles)
|
||||
{
|
||||
// Update Main.Tile first so that when tile sqaure is sent it is correct
|
||||
foreach (KeyValuePair<Vector2, Tile> entry in destroyedTiles)
|
||||
{
|
||||
Main.tile[(int)entry.Key.X, (int)entry.Key.Y] = entry.Value;
|
||||
Log.Debug(string.Format("Reverted DestroyedTile(TileXY:{0}_{1}, Type:{2})",
|
||||
entry.Key.X, entry.Key.Y, Main.tile[(int)entry.Key.X, (int)entry.Key.Y].type));
|
||||
}
|
||||
// Send all players updated tile sqaures
|
||||
foreach (Vector2 coords in destroyedTiles.Keys)
|
||||
{
|
||||
TSPlayer.All.SendTileSquare((int)coords.X, (int)coords.Y, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,29 +17,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Terraria;
|
||||
using TerrariaAPI;
|
||||
using TerrariaAPI.Hooks;
|
||||
using System.Text;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
[APIVersion(1, 3)]
|
||||
[APIVersion(1, 5)]
|
||||
public class TShock : TerrariaPlugin
|
||||
{
|
||||
public static TSPlayer[] Players = new TSPlayer[Main.maxPlayers];
|
||||
public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
public static readonly string VersionCodename = "Lol, packet changes.";
|
||||
|
||||
public static readonly string SavePath = "tshock";
|
||||
|
||||
public static readonly Version VersionNum = new Version(2, 1, 0, 6);
|
||||
|
||||
public static readonly string VersionCodename = "Forgot to increase the version.";
|
||||
|
||||
public static TSPlayer[] Players = new TSPlayer[Main.maxPlayers];
|
||||
public static BanManager Bans = new BanManager(Path.Combine(SavePath, "bans.txt"));
|
||||
public static BackupManager Backups = new BackupManager(Path.Combine(SavePath, "backups"));
|
||||
|
||||
public override Version Version
|
||||
{
|
||||
|
|
@ -74,6 +76,7 @@ namespace TShockAPI
|
|||
Console.WriteLine(version);
|
||||
|
||||
Log.Initialize(Path.Combine(SavePath, "log.txt"), LogLevel.All, false);
|
||||
|
||||
Log.Info(version);
|
||||
Log.Info("Starting...");
|
||||
|
||||
|
|
@ -99,6 +102,18 @@ namespace TShockAPI
|
|||
Commands.InitCommands();
|
||||
Log.Info("Commands initialized");
|
||||
|
||||
RegionManager.ReadAllSettings();
|
||||
WarpsManager.ReadAllSettings();
|
||||
ItemManager.LoadBans();
|
||||
|
||||
|
||||
Main.autoSave = ConfigurationManager.AutoSave;
|
||||
Backups.KeepFor = ConfigurationManager.BackupKeepFor;
|
||||
Backups.Interval = ConfigurationManager.BackupInterval;
|
||||
|
||||
Log.ConsoleInfo("AutoSave " + (ConfigurationManager.AutoSave ? "Enabled" : "Disabled"));
|
||||
Log.ConsoleInfo("Backups " + (Backups.Interval > 0 ? "Enabled" : "Disabled"));
|
||||
|
||||
HandleCommandLine(Environment.GetCommandLineArgs());
|
||||
}
|
||||
|
||||
|
|
@ -176,17 +191,19 @@ namespace TShockAPI
|
|||
private void OnUpdate(GameTime time)
|
||||
{
|
||||
UpdateManager.UpdateProcedureCheck();
|
||||
|
||||
if (Backups.IsBackupTime)
|
||||
Backups.Backup();
|
||||
|
||||
foreach (TSPlayer player in TShock.Players)
|
||||
{
|
||||
if (player != null && player.Active)
|
||||
{
|
||||
if (player.TileThreshold >= 20)
|
||||
if (player.TileThreshold >= ConfigurationManager.TileThreshold)
|
||||
{
|
||||
if (Tools.HandleTntUser(player, "Kill tile abuse detected."))
|
||||
{
|
||||
RevertKillTile(player);
|
||||
player.TileThreshold = 0;
|
||||
player.TilesDestroyed.Clear();
|
||||
TSPlayer.Server.RevertKillTile(player.TilesDestroyed);
|
||||
}
|
||||
else if (player.TileThreshold > 0)
|
||||
{
|
||||
|
|
@ -198,6 +215,20 @@ namespace TShockAPI
|
|||
else if (player.TileThreshold > 0)
|
||||
{
|
||||
player.TileThreshold = 0;
|
||||
player.TilesDestroyed.Clear();
|
||||
}
|
||||
|
||||
if (!player.Group.HasPermission("usebanneditem"))
|
||||
{
|
||||
var inv = Main.player[player.Index].inventory;
|
||||
for (int i = 0; i < inv.Length; i++)
|
||||
{
|
||||
if (inv[i] != null && ItemManager.ItemIsBanned(inv[i].name))
|
||||
{
|
||||
player.Disconnect("Using banned item: " + inv[i].name + ", remove it and rejoin");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -211,8 +242,7 @@ namespace TShockAPI
|
|||
var player = new TSPlayer(ply);
|
||||
player.Group = Tools.GetGroupForIP(player.IP);
|
||||
|
||||
if (Tools.ActivePlayers() + 1 > ConfigurationManager.MaxSlots &&
|
||||
!player.Group.HasPermission("reservedslot"))
|
||||
if (Tools.ActivePlayers() + 1 > ConfigurationManager.MaxSlots && !player.Group.HasPermission("reservedslot"))
|
||||
{
|
||||
Tools.ForceKick(player, "Server is full");
|
||||
handler.Handled = true;
|
||||
|
|
@ -233,7 +263,9 @@ namespace TShockAPI
|
|||
}
|
||||
|
||||
Players[ply] = player;
|
||||
Netplay.serverSock[ply].spamCheck = ConfigurationManager.SpamChecks;
|
||||
Players[ply].InitSpawn = false;
|
||||
|
||||
Netplay.spamCheck = ConfigurationManager.SpamChecks;
|
||||
}
|
||||
|
||||
private void OnLeave(int ply)
|
||||
|
|
@ -245,12 +277,18 @@ namespace TShockAPI
|
|||
if (tsplr != null && tsplr.ReceivedInfo)
|
||||
Log.Info(string.Format("{0} left.", tsplr.Name));
|
||||
|
||||
if (ConfigurationManager.RememberLeavePos)
|
||||
{
|
||||
RemeberedPosManager.RemeberedPosistions.Add(new RemeberedPos(Players[ply].IP, new Vector2(Players[ply].X / 16, (Players[ply].Y / 16) + 3)));
|
||||
RemeberedPosManager.WriteSettings();
|
||||
}
|
||||
|
||||
Players[ply] = null;
|
||||
}
|
||||
|
||||
private void OnChat(messageBuffer msg, int ply, string text, HandledEventArgs e)
|
||||
{
|
||||
if (Main.netMode != 2)
|
||||
if (Main.netMode != 2 || e.Handled)
|
||||
return;
|
||||
|
||||
if (msg.whoAmI != ply)
|
||||
|
|
@ -287,6 +325,9 @@ namespace TShockAPI
|
|||
/// <param name="e"></param>
|
||||
private void ServerHooks_OnCommand(string text, HandledEventArgs e)
|
||||
{
|
||||
if (e.Handled)
|
||||
return;
|
||||
|
||||
// Damn you ThreadStatic and Redigit
|
||||
if (Main.rand == null)
|
||||
{
|
||||
|
|
@ -319,61 +360,94 @@ namespace TShockAPI
|
|||
{
|
||||
Log.Info(string.Format("Server said: {0}", text.Remove(0, 4)));
|
||||
}
|
||||
else if (text == "autosave")
|
||||
{
|
||||
Main.autoSave = ConfigurationManager.AutoSave = !ConfigurationManager.AutoSave;
|
||||
Log.ConsoleInfo("AutoSave " + (ConfigurationManager.AutoSave ? "Enabled" : "Disabled"));
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (text.StartsWith("/"))
|
||||
{
|
||||
if (Commands.HandleCommand(TSPlayer.Server, text))
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void GetData(GetDataEventArgs e)
|
||||
{
|
||||
PacketTypes type = (PacketTypes) e.MsgID;
|
||||
if (Main.netMode != 2 || e.Handled)
|
||||
return;
|
||||
|
||||
PacketTypes type = e.MsgID;
|
||||
TSPlayer player = Players[e.Msg.whoAmI];
|
||||
|
||||
if (!player.ConnectionAlive)
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Main.verboseNetplay)
|
||||
Debug.WriteLine("{0:X} ({2}): {3} ({1:XX})", player.Index, (byte) type, player.TPlayer.dead ? "dead " : "alive", type.ToString());
|
||||
Debug.WriteLine("{0:X} ({2}): {3} ({1:XX})", player.Index, (byte)type, player.TPlayer.dead ? "dead " : "alive", type.ToString());
|
||||
|
||||
using (var data = new MemoryStream(e.Msg.readBuffer, e.Index, e.Length))
|
||||
// Stop accepting updates from player as this player is going to be kicked/banned during OnUpdate (different thread so can produce race conditions)
|
||||
if ((ConfigurationManager.BanTnt || ConfigurationManager.KickTnt) && player.TileThreshold >= ConfigurationManager.TileThreshold && !player.Group.HasPermission("ignoregriefdetection"))
|
||||
{
|
||||
try
|
||||
Log.Debug("Rejecting " + type + " from " + player.Name + " as this player is about to be kicked");
|
||||
e.Handled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var data = new MemoryStream(e.Msg.readBuffer, e.Index, e.Length))
|
||||
{
|
||||
if (GetDataHandlers.HandlerGetData(type, player, data))
|
||||
e.Handled = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
try
|
||||
{
|
||||
if (GetDataHandlers.HandlerGetData(type, player, data))
|
||||
e.Handled = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGreetPlayer(int who, HandledEventArgs e)
|
||||
{
|
||||
if (Main.netMode != 2)
|
||||
if (Main.netMode != 2 || e.Handled)
|
||||
return;
|
||||
|
||||
TSPlayer player = Players[who];
|
||||
Log.Info(string.Format("{0} ({1}) from '{2}' group joined.", player.Name, player.IP, player.Group.Name));
|
||||
|
||||
Tools.ShowFileToUser(player, "motd.txt");
|
||||
if (HackedHealth(who))
|
||||
if (HackedHealth(player))
|
||||
{
|
||||
Tools.HandleCheater(player, "Hacked health.");
|
||||
}
|
||||
if (ConfigurationManager.PermaPvp)
|
||||
{
|
||||
Main.player[who].hostile = true;
|
||||
NetMessage.SendData(30, -1, -1, "", who);
|
||||
player.SetPvP(true);
|
||||
}
|
||||
if (Players[who].Group.HasPermission("causeevents") && ConfigurationManager.InfiniteInvasion)
|
||||
{
|
||||
StartInvasion();
|
||||
}
|
||||
if (ConfigurationManager.RememberLeavePos)
|
||||
{
|
||||
foreach (RemeberedPos playerIP in RemeberedPosManager.RemeberedPosistions)
|
||||
{
|
||||
if (playerIP.IP == player.IP)
|
||||
{
|
||||
player.Teleport((int)playerIP.Pos.X, (int)playerIP.Pos.Y);
|
||||
RemeberedPosManager.RemeberedPosistions.Remove(playerIP);
|
||||
RemeberedPosManager.WriteSettings();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
|
@ -393,24 +467,6 @@ namespace TShockAPI
|
|||
* Useful stuff:
|
||||
* */
|
||||
|
||||
public static void Teleport(int ply, int x, int y)
|
||||
{
|
||||
Main.player[ply].position.X = x;
|
||||
Main.player[ply].position.Y = y;
|
||||
NetMessage.SendData(0x0d, -1, ply, "", ply);
|
||||
NetMessage.SendData(0x0d, -1, -1, "", ply);
|
||||
NetMessage.syncPlayers();
|
||||
}
|
||||
|
||||
public static void Teleport(int ply, float x, float y)
|
||||
{
|
||||
Main.player[ply].position.X = x;
|
||||
Main.player[ply].position.Y = y;
|
||||
NetMessage.SendData(0x0d, -1, ply, "", ply);
|
||||
NetMessage.SendData(0x0d, -1, -1, "", ply);
|
||||
NetMessage.syncPlayers();
|
||||
}
|
||||
|
||||
public static void StartInvasion()
|
||||
{
|
||||
Main.invasionType = 1;
|
||||
|
|
@ -465,75 +521,6 @@ namespace TShockAPI
|
|||
}
|
||||
}
|
||||
|
||||
public static void UpdateInventories()
|
||||
{
|
||||
for (int i = 0; i < Main.player.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < 44; j++)
|
||||
{
|
||||
for (int h = 0; h < Main.player.Length; h++)
|
||||
NetMessage.SendData(5, h, i, Main.player[i].inventory[j].name, i, j, 0f, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdatePlayers()
|
||||
{
|
||||
for (int i = 0; i < Main.player.Length; i++)
|
||||
{
|
||||
for (int h = 0; h < Main.player.Length; h++)
|
||||
NetMessage.SendData(0x0d, i, -1, "", h);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PlayerDamage(TSPlayer player, int damage)
|
||||
{
|
||||
NetMessage.SendData(26, -1, -1, "", player.Index, ((new Random()).Next(-1, 1)), damage, (float)0);
|
||||
}
|
||||
|
||||
public static void SendTileSquare(TSPlayer player, int x, int y, int size = 10)
|
||||
{
|
||||
NetMessage.SendData(20, player.Index, -1, "", size, (float)(x - (size / 2)), (float)(y - (size / 2)), 0f);
|
||||
}
|
||||
|
||||
//TODO : Notify the player if there is more than one match. (or do we want a First() kinda thing?)
|
||||
public static int GetNPCID(string name, bool exact = false)
|
||||
{
|
||||
NPC npc = new NPC();
|
||||
for (int i = 1; i < Main.maxNPCTypes; i++)
|
||||
{
|
||||
if (exact)
|
||||
{
|
||||
//Method #1 - must be exact match, allows support for different coloured slimes
|
||||
npc.SetDefaults(name);
|
||||
if (npc.name == name)
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Method #2 - allows impartial matching
|
||||
name = name.ToLower();
|
||||
npc.SetDefaults(i);
|
||||
if (npc.name.ToLower().StartsWith(name))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int GetItemID(string name)
|
||||
{
|
||||
Item item = new Item();
|
||||
name = name.ToLower();
|
||||
for (int i = 1; i < Main.maxItemTypes; i++)
|
||||
{
|
||||
item.SetDefaults(i);
|
||||
if (item.name.ToLower().StartsWith(name))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static bool CheckSpawn(int x, int y)
|
||||
{
|
||||
Vector2 tile = new Vector2(x, y);
|
||||
|
|
@ -545,25 +532,12 @@ namespace TShockAPI
|
|||
return true;
|
||||
}
|
||||
|
||||
public static void RevertKillTile(TSPlayer player)
|
||||
public static bool HackedHealth(TSPlayer player)
|
||||
{
|
||||
Tile[] tiles = new Tile[player.TilesDestroyed.Count];
|
||||
player.TilesDestroyed.Values.CopyTo(tiles, 0);
|
||||
Vector2[] positions = new Vector2[player.TilesDestroyed.Count];
|
||||
player.TilesDestroyed.Keys.CopyTo(positions, 0);
|
||||
for (int i = (player.TilesDestroyed.Count - 1); i >= 0; i--)
|
||||
{
|
||||
Main.tile[(int)positions[i].X, (int)positions[i].Y] = tiles[i];
|
||||
NetMessage.SendData(17, -1, -1, "", 1, positions[i].X, positions[i].Y, (float)0);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HackedHealth(int ply)
|
||||
{
|
||||
return (Main.player[ply].statManaMax > 200) ||
|
||||
(Main.player[ply].statMana > 200) ||
|
||||
(Main.player[ply].statLifeMax > 400) ||
|
||||
(Main.player[ply].statLife > 400);
|
||||
return (player.TPlayer.statManaMax > 200) ||
|
||||
(player.TPlayer.statMana > 200) ||
|
||||
(player.TPlayer.statLifeMax > 400) ||
|
||||
(player.TPlayer.statLife > 400);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,21 @@
|
|||
<AssemblyName>TShockAPI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
|
@ -47,16 +62,19 @@
|
|||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="TerrariaServer">
|
||||
<HintPath>.\TerrariaServer.exe</HintPath>
|
||||
<Private>False</Private>
|
||||
<HintPath>TerrariaServerBins\TerrariaServer.exe</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="TerrariaServerAPI">
|
||||
<HintPath>.\TerrariaServerAPI.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
<HintPath>TerrariaServerBins\TerrariaServerAPI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="XNAHelpers">
|
||||
<HintPath>TerrariaServerBins\XNAHelpers.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BackupManager.cs" />
|
||||
<Compile Include="BanManager.cs" />
|
||||
<Compile Include="ItemManager.cs" />
|
||||
<Compile Include="Commands.cs" />
|
||||
<Compile Include="ConfigFile.cs" />
|
||||
<Compile Include="ConfigurationManager.cs" />
|
||||
|
|
@ -64,17 +82,19 @@
|
|||
<Compile Include="GetDataHandlers.cs" />
|
||||
<Compile Include="Group.cs" />
|
||||
<Compile Include="Log.cs" />
|
||||
<Compile Include="RegionManager.cs" />
|
||||
<Compile Include="RememberPosManager.cs" />
|
||||
<Compile Include="Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="StreamExt.cs" />
|
||||
<Compile Include="Tools.cs" />
|
||||
<Compile Include="TShock.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TSPlayer.cs" />
|
||||
<Compile Include="UpdateManager.cs" />
|
||||
<Compile Include="WarpsManager.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="config\groups.txt" />
|
||||
|
|
@ -89,14 +109,45 @@
|
|||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Windows Installer 3.1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="config\itembans.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>"$(SolutionDir)\myass.bat"</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_IncrementBeforeBuild="False" BuildVersion_StartDate="2011/6/17" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_BuildAction="Both" BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
BIN
TShockAPI/TerrariaServerBins/TerrariaServer.exe
Normal file
BIN
TShockAPI/TerrariaServerBins/TerrariaServer.exe
Normal file
Binary file not shown.
BIN
TShockAPI/TerrariaServerBins/TerrariaServerAPI.dll
Normal file
BIN
TShockAPI/TerrariaServerBins/TerrariaServerAPI.dll
Normal file
Binary file not shown.
BIN
TShockAPI/TerrariaServerBins/XNAHelpers.dll
Normal file
BIN
TShockAPI/TerrariaServerBins/XNAHelpers.dll
Normal file
Binary file not shown.
|
|
@ -19,20 +19,15 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Terraria;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
internal enum NPCList
|
||||
{
|
||||
WORLD_EATER = 0,
|
||||
EYE = 1,
|
||||
SKELETRON = 2
|
||||
}
|
||||
|
||||
internal class Tools
|
||||
{
|
||||
private static Random random = new Random();
|
||||
private static List<Group> groups = new List<Group>();
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -66,6 +61,25 @@ namespace TShockAPI
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a player and gets IP as string
|
||||
/// </summary>
|
||||
/// <param name="msg">Player name</param>
|
||||
public static string GetPlayerIP(string playername)
|
||||
{
|
||||
foreach (TSPlayer player in TShock.Players)
|
||||
{
|
||||
if (player != null && player.Active)
|
||||
{
|
||||
if (playername.ToLower() == player.Name.ToLower())
|
||||
{
|
||||
return player.IP;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// It's a clamp function
|
||||
/// </summary>
|
||||
|
|
@ -118,7 +132,7 @@ namespace TShockAPI
|
|||
TSPlayer.Server.SendMessage(log, color);
|
||||
foreach (TSPlayer player in TShock.Players)
|
||||
{
|
||||
if (player != null && player.Active && player.Group.HasPermission("logs"))
|
||||
if (player != null && player.Active && player.Group.HasPermission("logs") && player.DisplayLogs)
|
||||
player.SendMessage(log, color);
|
||||
}
|
||||
}
|
||||
|
|
@ -163,31 +177,115 @@ namespace TShockAPI
|
|||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an NPC
|
||||
/// </summary>
|
||||
/// <param name="type">Type is defined in the enum NPC list</param>
|
||||
/// <param name="player">int player that the npc targets</param>
|
||||
public static void NewNPC(NPCList type, TSPlayer player)
|
||||
public static void GetRandomClearTileWithInRange(int startTileX, int startTileY, int tileXRange, int tileYRange, out int tileX, out int tileY)
|
||||
{
|
||||
switch (type)
|
||||
int j = 0;
|
||||
do
|
||||
{
|
||||
case NPCList.WORLD_EATER:
|
||||
WorldGen.shadowOrbSmashed = true;
|
||||
WorldGen.shadowOrbCount = 3;
|
||||
int w = NPC.NewNPC((int)player.X, (int)player.Y, 13, 1);
|
||||
Main.npc[w].target = player.Index;
|
||||
break;
|
||||
case NPCList.EYE:
|
||||
Main.time = 4861;
|
||||
Main.dayTime = false;
|
||||
WorldGen.spawnEye = true;
|
||||
break;
|
||||
case NPCList.SKELETRON:
|
||||
int enpeecee = NPC.NewNPC((int)player.X, (int)player.Y, 0x23, 0);
|
||||
Main.npc[enpeecee].netUpdate = true;
|
||||
if (j == 100)
|
||||
{
|
||||
tileX = startTileX;
|
||||
tileY = startTileY;
|
||||
break;
|
||||
}
|
||||
|
||||
tileX = startTileX + random.Next(tileXRange * -1, tileXRange);
|
||||
tileY = startTileY + random.Next(tileYRange * -1, tileYRange);
|
||||
j++;
|
||||
}
|
||||
while (TileValid(tileX, tileY) && !TileClear(tileX, tileY));
|
||||
}
|
||||
|
||||
private static bool TileValid(int tileX, int tileY)
|
||||
{
|
||||
return tileX >= 0 && tileX <= Main.maxTilesX && tileY >= 0 && tileY <= Main.maxTilesY;
|
||||
}
|
||||
|
||||
private static bool TileClear(int tileX, int tileY)
|
||||
{
|
||||
return !Main.tile[tileX, tileY].active;
|
||||
}
|
||||
|
||||
public static List<Item> GetItemByIdOrName(string idOrName)
|
||||
{
|
||||
int type = -1;
|
||||
if (int.TryParse(idOrName, out type))
|
||||
{
|
||||
return new List<Item> { GetItemById(type) };
|
||||
}
|
||||
return GetItemByName(idOrName);
|
||||
}
|
||||
|
||||
public static Item GetItemById(int id)
|
||||
{
|
||||
Item item = new Item();
|
||||
item.SetDefaults(id);
|
||||
return item;
|
||||
}
|
||||
|
||||
public static List<Item> GetItemByName(string name)
|
||||
{
|
||||
//Method #1 - must be exact match, allows support for different pickaxes/hammers/swords etc
|
||||
for (int i = 1; i < Main.maxItemTypes; i++)
|
||||
{
|
||||
Item item = new Item();
|
||||
item.SetDefaults(name);
|
||||
if (item.name == name)
|
||||
return new List<Item> { item };
|
||||
}
|
||||
//Method #2 - allows impartial matching
|
||||
var found = new List<Item>();
|
||||
for (int i = 1; i < Main.maxItemTypes; i++)
|
||||
{
|
||||
Item item = new Item();
|
||||
item.SetDefaults(i);
|
||||
if (item.name.ToLower() == name.ToLower())
|
||||
return new List<Item> { item };
|
||||
if (item.name.ToLower().StartsWith(name.ToLower()))
|
||||
found.Add(item);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public static List<NPC> GetNPCByIdOrName(string idOrName)
|
||||
{
|
||||
int type = -1;
|
||||
if (int.TryParse(idOrName, out type))
|
||||
{
|
||||
return new List<NPC> { GetNPCById(type) };
|
||||
}
|
||||
return GetNPCByName(idOrName);
|
||||
}
|
||||
|
||||
public static NPC GetNPCById(int id)
|
||||
{
|
||||
NPC npc = new NPC();
|
||||
npc.SetDefaults(id);
|
||||
return npc;
|
||||
}
|
||||
|
||||
public static List<NPC> GetNPCByName(string name)
|
||||
{
|
||||
//Method #1 - must be exact match, allows support for different coloured slimes
|
||||
for (int i = 1; i < Main.maxNPCTypes; i++)
|
||||
{
|
||||
NPC npc = new NPC();
|
||||
npc.SetDefaults(name);
|
||||
if (npc.name == name)
|
||||
return new List<NPC> { npc };
|
||||
}
|
||||
//Method #2 - allows impartial matching
|
||||
var found = new List<NPC>();
|
||||
for (int i = 1; i < Main.maxNPCTypes; i++)
|
||||
{
|
||||
NPC npc = new NPC();
|
||||
npc.SetDefaults(i);
|
||||
if (npc.name.ToLower() == name.ToLower())
|
||||
return new List<NPC> { npc };
|
||||
if (npc.name.ToLower().StartsWith(name.ToLower()))
|
||||
found.Add(npc);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -201,7 +299,7 @@ namespace TShockAPI
|
|||
{
|
||||
if (player != null && player.Active)
|
||||
{
|
||||
Tools.ForceKick(player, reason);
|
||||
ForceKick(player, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -215,7 +313,7 @@ namespace TShockAPI
|
|||
{
|
||||
if (!player.ConnectionAlive)
|
||||
return;
|
||||
NetMessage.SendData(0x2, player.Index, -1, reason, 0x0, 0f, 0f, 0f);
|
||||
player.Disconnect(reason);
|
||||
Log.Info(string.Format("{0} was force kicked for : {1}", player.IP, reason));
|
||||
}
|
||||
|
||||
|
|
@ -231,12 +329,12 @@ namespace TShockAPI
|
|||
if (!player.Group.HasPermission("immunetokick"))
|
||||
{
|
||||
string playerName = player.Name;
|
||||
NetMessage.SendData(0x2, player.Index, -1, string.Format("Kicked: {0}", reason), 0x0, 0f, 0f, 0f);
|
||||
player.Disconnect(string.Format("Kicked: {0}", reason));
|
||||
Log.Info(string.Format("Kicked {0} for : {1}", playerName, reason));
|
||||
if (adminUserName.Length == 0)
|
||||
Broadcast(string.Format("{0} was kicked for {1}", playerName, reason.ToLower()));
|
||||
else
|
||||
Tools.Broadcast(string.Format("{0} kicked {1} for {2}", adminUserName, playerName, reason.ToLower()));
|
||||
Broadcast(string.Format("{0} kicked {1} for {2}", adminUserName, playerName, reason.ToLower()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -256,12 +354,12 @@ namespace TShockAPI
|
|||
string ip = player.IP;
|
||||
string playerName = player.Name;
|
||||
TShock.Bans.AddBan(ip, playerName, reason);
|
||||
NetMessage.SendData(0x2, player.Index, -1, string.Format("Banned: {0}", reason), 0x0, 0f, 0f, 0f);
|
||||
player.Disconnect(string.Format("Banned: {0}", reason));
|
||||
Log.Info(string.Format("Banned {0} for : {1}", playerName, reason));
|
||||
if (adminUserName.Length == 0)
|
||||
Broadcast(string.Format("{0} was banned for {1}", playerName, reason.ToLower()));
|
||||
else
|
||||
Tools.Broadcast(string.Format("{0} banned {1} for {2}", adminUserName, playerName, reason.ToLower()));
|
||||
Broadcast(string.Format("{0} banned {1} for {2}", adminUserName, playerName, reason.ToLower()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -458,13 +556,35 @@ namespace TShockAPI
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if (args[0].Equals(ip))
|
||||
try
|
||||
{
|
||||
return GetGroup(args[1]);
|
||||
var hi = GetIPv4Address(args[0]);
|
||||
if (GetIPv4Address(args[0]).Equals(ip))
|
||||
return GetGroup(args[1]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{ Log.Error(ex.ToString()); }
|
||||
}
|
||||
sr.Close();
|
||||
return GetGroup("default");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an IPv4 address from a DNS query
|
||||
/// </summary>
|
||||
/// <param name="hostname">string ip</param>
|
||||
public static string GetIPv4Address(string hostname)
|
||||
{
|
||||
string IP4Address = String.Empty;
|
||||
foreach (IPAddress IPA in Dns.GetHostAddresses(hostname))
|
||||
{
|
||||
if (IPA.AddressFamily.ToString() == "InterNetwork")
|
||||
{
|
||||
IP4Address = IPA.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return IP4Address;
|
||||
}
|
||||
}
|
||||
}
|
||||
184
TShockAPI/WarpsManager.cs
Normal file
184
TShockAPI/WarpsManager.cs
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Xml;
|
||||
using Terraria;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
class WarpsManager
|
||||
{
|
||||
public static List<Warp> Warps = new List<Warp>();
|
||||
|
||||
public static bool AddWarp(int x, int y, string name, string worldname)
|
||||
{
|
||||
foreach (Warp nametest in Warps)
|
||||
{
|
||||
if (name.ToLower() == nametest.WarpName.ToLower())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Warps.Add(new Warp(new Vector2(x, y), name, worldname));
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool DeleteWarp(string name)
|
||||
{
|
||||
foreach (Warp nametest in Warps)
|
||||
{
|
||||
if (name.ToLower() == nametest.WarpName.ToLower() && nametest.WorldWarpName == Main.worldName)
|
||||
{
|
||||
Warps.Remove(nametest);
|
||||
WriteSettings();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Vector2 FindWarp(string name)
|
||||
{
|
||||
foreach (Warp nametest in Warps)
|
||||
{
|
||||
if (name.ToLower() == nametest.WarpName.ToLower() && nametest.WorldWarpName == Main.worldName)
|
||||
{
|
||||
return nametest.WarpPos;
|
||||
}
|
||||
}
|
||||
return Vector2.Zero;
|
||||
}
|
||||
|
||||
public static void WriteSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
|
||||
xmlWriterSettings.Indent = true;
|
||||
xmlWriterSettings.NewLineChars = Environment.NewLine;
|
||||
|
||||
using (XmlWriter settingsw = XmlWriter.Create(FileTools.WarpsPath, xmlWriterSettings))
|
||||
{
|
||||
settingsw.WriteStartDocument();
|
||||
settingsw.WriteStartElement("Warps");
|
||||
|
||||
foreach (Warp warp in Warps)
|
||||
{
|
||||
settingsw.WriteStartElement("Warp");
|
||||
settingsw.WriteElementString("WarpName", warp.WarpName);
|
||||
settingsw.WriteElementString("X", warp.WarpPos.X.ToString());
|
||||
settingsw.WriteElementString("Y", warp.WarpPos.Y.ToString());
|
||||
settingsw.WriteElementString("WorldName", warp.WorldWarpName);
|
||||
settingsw.WriteEndElement();
|
||||
}
|
||||
|
||||
settingsw.WriteEndElement();
|
||||
settingsw.WriteEndDocument();
|
||||
}
|
||||
Log.Info("Wrote Warps");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Info("Could not write Warps");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReadAllSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
|
||||
xmlReaderSettings.IgnoreWhitespace = true;
|
||||
|
||||
using (XmlReader settingr = XmlReader.Create(FileTools.WarpsPath, xmlReaderSettings))
|
||||
{
|
||||
while (settingr.Read())
|
||||
{
|
||||
if (settingr.IsStartElement())
|
||||
{
|
||||
switch (settingr.Name)
|
||||
{
|
||||
case "Warps":
|
||||
{
|
||||
break;
|
||||
}
|
||||
case "Warp":
|
||||
{
|
||||
if (settingr.Read())
|
||||
{
|
||||
string name = string.Empty;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
string worldname = string.Empty;
|
||||
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
name = settingr.Value;
|
||||
else
|
||||
Log.Warn("Warp name is empty, This warp will not work");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
Int32.TryParse(settingr.Value, out x);
|
||||
else
|
||||
Log.Warn("x for warp " + name + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
Int32.TryParse(settingr.Value, out y);
|
||||
else
|
||||
Log.Warn("y for warp " + name + " is empty");
|
||||
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
settingr.Read();
|
||||
if (settingr.Value != "" || settingr.Value != null)
|
||||
worldname = settingr.Value;
|
||||
else
|
||||
Log.Warn("Worldname for warp " + name + " is empty");
|
||||
|
||||
AddWarp(x, y, name, worldname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.Info("Read Warps");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Info("Could not read Warps");
|
||||
WriteSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Warp
|
||||
{
|
||||
public Vector2 WarpPos { get; set; }
|
||||
public string WarpName { get; set; }
|
||||
public string WorldWarpName { get; set; }
|
||||
|
||||
public Warp(Vector2 warppos, string name, string worldname)
|
||||
{
|
||||
WarpPos = warppos;
|
||||
WarpName = name;
|
||||
WorldWarpName = worldname;
|
||||
}
|
||||
|
||||
public Warp()
|
||||
{
|
||||
WarpPos = Vector2.Zero;
|
||||
WarpName = null;
|
||||
WorldWarpName = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,14 +8,36 @@
|
|||
#ALWAYS DECLARE A GROUP'S PARENT BEFORE YOU DECLARE THE GROUP
|
||||
|
||||
#currently avaliable permissions:
|
||||
#kick ban ignorecheatdetection
|
||||
#maintenance cfg causeevents spawnboss tp
|
||||
#spawnmob cheat kill pvpfun
|
||||
#immunetoban immunetokick editspawn
|
||||
#ignoregriefdetection reservedslot
|
||||
#reservedslot - reserved slot for player
|
||||
#canwater - allow players to use water
|
||||
#canlava - allow playes to use lava
|
||||
#warp - allow players to use warps
|
||||
#kick - kick users
|
||||
#ban - ban players by name or ip
|
||||
#unban - unban players by name or ip
|
||||
#whitelist - add ip to whitelist
|
||||
#maintenance - check for updates/turn off server
|
||||
#causeevents - allow player to drop star/meteor and start invasion/bloodmoon
|
||||
#spawnboss - allow player to spawn bosses
|
||||
#spawnmob - allow player to spawn any npcs
|
||||
#tp - allow player to teleport
|
||||
#managewarp - allow player to add/delete warp locations
|
||||
#editspawn - allow player to enable/disable build protection
|
||||
#cfg - allow player to view/change tshock configuration
|
||||
#time - allow player to change time
|
||||
#pvpfun - enable pvpfun commands
|
||||
#logs - notify player when any command is executed
|
||||
#kill - allow player to kill others
|
||||
#butcher - allow player to kill all alive monsters
|
||||
#cheat - allow player to spawn items and heal self
|
||||
#immunetokick - player can't be kick
|
||||
#immunetoban - player can't be banned
|
||||
#ignorecheatdetection - allow player to cheat (health/mana cheats)
|
||||
#ignoregriefdetection - allow player to grief (use explosives, water, lava even if they dont have premission to)
|
||||
#usebanneditem - allows player to use banned items
|
||||
|
||||
default null canwater canlava
|
||||
default null canwater canlava warp
|
||||
vip default reservedslot
|
||||
newadmin default kick editspawn reservedslot
|
||||
admin newadmin ban unban causeevents spawnboss spawnmob tp immunetokick kill logs
|
||||
trustedadmin admin maintenance cfg cheat pvpfun ignorecheatdetection immunetoban ignoregriefdetection
|
||||
admin newadmin ban unban whitelist causeevents spawnboss spawnmob managewarp time tp pvpfun kill logs immunetokick
|
||||
trustedadmin admin maintenance cfg butcher cheat immunetoban ignorecheatdetection ignoregriefdetection usebanneditem
|
||||
2
TShockAPI/config/itembans.txt
Normal file
2
TShockAPI/config/itembans.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#see https://github.com/TShock/TShock/wiki/Item-List for a list of item ids
|
||||
#List each banned item ID below this, with each on a new line
|
||||
12
Terraria.sln
12
Terraria.sln
|
|
@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 11.00
|
|||
# Visual Studio 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockAPI", "TShockAPI\TShockAPI.csproj", "{49606449-072B-4CF5-8088-AA49DA586694}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update", "Update\Update.csproj", "{AF322FAB-9A32-43AA-A01A-76B2A039F711}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -25,16 +23,6 @@ Global
|
|||
{49606449-072B-4CF5-8088-AA49DA586694}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{49606449-072B-4CF5-8088-AA49DA586694}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{49606449-072B-4CF5-8088-AA49DA586694}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Debug|x86.Build.0 = Debug|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Release|x86.ActiveCfg = Release|x86
|
||||
{AF322FAB-9A32-43AA-A01A-76B2A039F711}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string data;
|
||||
string procname = "cmd.exe";
|
||||
string procargs = "/c echo finalizing update&&ping 127.0.0.1 -n 2&&del UpdateTShock.exe";
|
||||
try
|
||||
{
|
||||
StreamReader sr = new StreamReader("pn");
|
||||
procname = sr.ReadToEnd();
|
||||
sr.Close();
|
||||
string[] datat = procname.Split(' ');
|
||||
procname = datat[0];
|
||||
procargs = "";
|
||||
for (int i = 0; i < datat.Count(); i++)
|
||||
{
|
||||
procargs += datat[i] + " ";
|
||||
}
|
||||
|
||||
File.Delete("pn");
|
||||
|
||||
sr.Dispose();
|
||||
|
||||
sr = new StreamReader("pid");
|
||||
data = sr.ReadToEnd();
|
||||
sr.Close();
|
||||
|
||||
File.Delete("pid");
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
data = "";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Process TServer = Process.GetProcessById(Convert.ToInt32(data));
|
||||
while (!TServer.HasExited)
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo("serverplugins");
|
||||
FileInfo[] fi = di.GetFiles();
|
||||
for (int i = 0; i < fi.Length; i ++ )
|
||||
{
|
||||
if (fi[i].Name.ToLowerInvariant().Contains("tshockapi"))
|
||||
{
|
||||
fi[i].Delete();
|
||||
}
|
||||
}
|
||||
if (System.IO.File.Exists("serverplugins/TShockAPI.dll"))
|
||||
{
|
||||
System.IO.File.Delete("serverplugins/TShockAPI.dll");
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
}
|
||||
|
||||
BinaryWriter bw = new BinaryWriter(new FileStream("serverplugins/TShockAPI.dll", FileMode.Create));
|
||||
bw.Write(Resources.TShockAPI);
|
||||
bw.Close();
|
||||
|
||||
Process.Start(new ProcessStartInfo(procname, procargs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Update")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("Update")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("c809c4c8-97b2-46f1-bbc0-b4a3ae955ac1")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
70
Update/Resources.Designer.cs
generated
70
Update/Resources.Designer.cs
generated
|
|
@ -1,70 +0,0 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.225
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Update {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Update.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal static byte[] TShockAPI {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("TShockAPI", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="TShockAPI" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\TShockAPI\bin\Release\TShockAPI.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{AF322FAB-9A32-43AA-A01A-76B2A039F711}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Update</RootNamespace>
|
||||
<AssemblyName>UpdateTShock</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\TShockAPI.dll" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
Loading…
Add table
Add a link
Reference in a new issue