Merge commit 'e465caa230' into general-devel-2

This commit is contained in:
Deathmax 2011-06-27 22:29:36 +08:00
commit 07de1159fd
37 changed files with 2597 additions and 1560 deletions

11
GUIDELINES Normal file
View 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/).

View 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

View file

@ -30,10 +30,11 @@ namespace TShockAPI
public bool BanCheaters = true; public bool BanCheaters = true;
public bool KickGriefers = true; public bool KickGriefers = true;
public bool BanGriefers = true; public bool BanGriefers = true;
public bool BanKillTileAbusers; public bool BanKillTileAbusers = true;
public bool KickKillTileAbusers; public bool KickKillTileAbusers = true;
public bool BanExplosives = true; public bool BanExplosives = true;
public bool KickExplosives = true; public bool KickExplosives = true;
public bool DisableExplosives = true;
public bool SpawnProtection = true; public bool SpawnProtection = true;
public int SpawnProtectionRadius = 5; public int SpawnProtectionRadius = 5;
public string DistributationAgent = "facepunch"; public string DistributationAgent = "facepunch";
@ -41,7 +42,22 @@ namespace TShockAPI
public bool RangeChecks = true; public bool RangeChecks = true;
public bool SpamChecks = false; public bool SpamChecks = false;
public bool DisableBuild = false; public bool DisableBuild = false;
public int TileThreshold = 20;
public float[] AdminChatRGB = {255, 0, 0}; public float[] AdminChatRGB = {255, 0, 0};
public string AdminChatPrefix = "(Admin) "; 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;
} }
} }

View file

@ -44,6 +44,7 @@ namespace TShockAPI
public static bool KickTnt = true; public static bool KickTnt = true;
public static bool BanBoom = true; public static bool BanBoom = true;
public static bool KickBoom = true; public static bool KickBoom = true;
public static bool DisableBoom = true;
public static bool SpawnProtect = true; public static bool SpawnProtect = true;
public static bool RangeChecks = true; public static bool RangeChecks = true;
public static int SpawnProtectRadius = 5; public static int SpawnProtectRadius = 5;
@ -54,6 +55,28 @@ namespace TShockAPI
public static bool DisableBuild = false; public static bool DisableBuild = false;
public static float[] AdminChatRGB = {255, 0, 0}; public static float[] AdminChatRGB = {255, 0, 0};
public static string AdminChatPrefix = "(Admin) "; 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() public static void ReadJsonConfiguration()
{ {
@ -76,6 +99,7 @@ namespace TShockAPI
KickTnt = cfg.KickKillTileAbusers; KickTnt = cfg.KickKillTileAbusers;
BanBoom = cfg.BanExplosives; BanBoom = cfg.BanExplosives;
KickBoom = cfg.KickExplosives; KickBoom = cfg.KickExplosives;
DisableBoom = cfg.DisableExplosives;
SpawnProtect = cfg.SpawnProtection; SpawnProtect = cfg.SpawnProtection;
SpawnProtectRadius = cfg.SpawnProtectionRadius; SpawnProtectRadius = cfg.SpawnProtectionRadius;
DistributationAgent = cfg.DistributationAgent; DistributationAgent = cfg.DistributationAgent;
@ -83,10 +107,19 @@ namespace TShockAPI
RangeChecks = cfg.RangeChecks; RangeChecks = cfg.RangeChecks;
SpamChecks = cfg.SpamChecks; SpamChecks = cfg.SpamChecks;
DisableBuild = cfg.DisableBuild; DisableBuild = cfg.DisableBuild;
TileThreshold = cfg.TileThreshold;
NPC.maxSpawns = DefaultMaxSpawns; NPC.maxSpawns = DefaultMaxSpawns;
NPC.defaultSpawnRate = DefaultSpawnRate; NPC.defaultSpawnRate = DefaultSpawnRate;
AdminChatRGB = cfg.AdminChatRGB; AdminChatRGB = cfg.AdminChatRGB;
AdminChatPrefix = cfg.AdminChatPrefix; 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() public static void WriteJsonConfiguration()
@ -103,18 +136,28 @@ namespace TShockAPI
cfg.BanCheaters = BanCheater; cfg.BanCheaters = BanCheater;
cfg.KickGriefers = KickGriefer; cfg.KickGriefers = KickGriefer;
cfg.BanGriefers = BanGriefer; cfg.BanGriefers = BanGriefer;
cfg.BanKillTileAbusers = BanGriefer; cfg.BanKillTileAbusers = BanTnt;
cfg.KickKillTileAbusers = KickGriefer; cfg.KickKillTileAbusers = KickTnt;
cfg.BanExplosives = BanBoom; cfg.BanExplosives = BanBoom;
cfg.KickExplosives = KickBoom; cfg.KickExplosives = KickBoom;
cfg.DisableExplosives = DisableBoom;
cfg.SpawnProtection = SpawnProtect; cfg.SpawnProtection = SpawnProtect;
cfg.SpawnProtectionRadius = SpawnProtectRadius; cfg.SpawnProtectionRadius = SpawnProtectRadius;
cfg.MaxSlots = MaxSlots; cfg.MaxSlots = MaxSlots;
cfg.RangeChecks = RangeChecks; cfg.RangeChecks = RangeChecks;
cfg.SpamChecks = SpamChecks; cfg.SpamChecks = SpamChecks;
cfg.DisableBuild = DisableBuild; cfg.DisableBuild = DisableBuild;
cfg.TileThreshold = TileThreshold;
cfg.AdminChatRGB = AdminChatRGB; cfg.AdminChatRGB = AdminChatRGB;
cfg.AdminChatPrefix = AdminChatPrefix; 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); string json = JsonConvert.SerializeObject(cfg, Formatting.Indented);
TextWriter tr = new StreamWriter(FileTools.ConfigPath); TextWriter tr = new StreamWriter(FileTools.ConfigPath);
tr.Write(json); tr.Write(json);

View file

@ -29,7 +29,11 @@ namespace TShockAPI
public static readonly string WhitelistPath = Path.Combine(TShock.SavePath, "whitelist.txt"); 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 GroupsPath = Path.Combine(TShock.SavePath, "groups.txt");
public static readonly string UsersPath = Path.Combine(TShock.SavePath, "users.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 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) public static void CreateFile(string file)
{ {
@ -60,6 +64,25 @@ namespace TShockAPI
CreateIfNot(WhitelistPath); CreateIfNot(WhitelistPath);
CreateIfNot(GroupsPath, Resources.groups); CreateIfNot(GroupsPath, Resources.groups);
CreateIfNot(UsersPath, Resources.users); 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 try
{ {
@ -100,7 +123,23 @@ namespace TShockAPI
TextReader tr = new StreamReader(WhitelistPath); TextReader tr = new StreamReader(WhitelistPath);
string whitelist = tr.ReadToEnd(); string whitelist = tr.ReadToEnd();
ip = Tools.GetRealIP(ip); 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;
} }
} }
} }

View file

@ -21,9 +21,9 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using StreamBinary;
using Terraria; using Terraria;
using TerrariaAPI; using TerrariaAPI;
using XNAHelpers;
namespace TShockAPI namespace TShockAPI
{ {
@ -108,6 +108,7 @@ namespace TShockAPI
{PacketTypes.TileKill, HandleTileKill}, {PacketTypes.TileKill, HandleTileKill},
{PacketTypes.PlayerKillMe, HandlePlayerKillMe}, {PacketTypes.PlayerKillMe, HandlePlayerKillMe},
{PacketTypes.LiquidSet, HandleLiquidSet}, {PacketTypes.LiquidSet, HandleLiquidSet},
{PacketTypes.PlayerSpawn, HandleSpawn},
}; };
} }
@ -132,21 +133,17 @@ namespace TShockAPI
{ {
byte playerid = args.Data.ReadInt8(); byte playerid = args.Data.ReadInt8();
byte hair = args.Data.ReadInt8(); byte hair = args.Data.ReadInt8();
Color hairColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8()); //Various colours here
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()); args.Data.Position += 21;
Color shirtColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8()); bool hardcore = args.Data.ReadBoolean();
Color underShirtColor = 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)));
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) if (hair >= Main.maxHair)
{ {
Tools.ForceKick(args.Player, "Hair crash exploit."); Tools.ForceKick(args.Player, "Hair crash exploit.");
return true; return true;
} }
if (name.Length > 32) if (name.Length > 32)
{ {
Tools.ForceKick(args.Player, "Name exceeded 32 characters."); Tools.ForceKick(args.Player, "Name exceeded 32 characters.");
@ -167,6 +164,12 @@ namespace TShockAPI
{ {
return Tools.HandleGriefer(args.Player, "Sent client info more than once"); 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; args.Player.ReceivedInfo = true;
return false; return false;
@ -205,17 +208,33 @@ namespace TShockAPI
if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32))) 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})", if (!(type == 1 && ((tiletype == 0 && args.Player.TPlayer.selectedItem == 114) || (tiletype == 53 && args.Player.TPlayer.selectedItem == 266))))
plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), tiletype)); {
return Tools.HandleGriefer(args.Player, "Placing impossible to place blocks."); 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 (ConfigurationManager.DisableBuild)
{ {
if (!args.Player.Group.HasPermission("editspawn")) if (!args.Player.Group.HasPermission("editspawn"))
{ {
args.Player.SendMessage("World protected from changes.", Color.Red); args.Player.SendMessage("World protected from changes.", Color.Red);
TShock.SendTileSquare(args.Player, x, y); args.Player.SendTileSquare(x, y);
return true; return true;
} }
} }
@ -227,7 +246,7 @@ namespace TShockAPI
if (flag) if (flag)
{ {
args.Player.SendMessage("Spawn protected from changes.", Color.Red); args.Player.SendMessage("Spawn protected from changes.", Color.Red);
TShock.SendTileSquare(args.Player, x, y); args.Player.SendTileSquare(x, y);
return true; return true;
} }
} }
@ -239,6 +258,13 @@ namespace TShockAPI
if (!args.Player.TilesDestroyed.ContainsKey(coords)) if (!args.Player.TilesDestroyed.ContainsKey(coords))
args.Player.TilesDestroyed.Add(coords, Main.tile[x, y]); 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; return false;
} }
@ -248,12 +274,16 @@ namespace TShockAPI
int id = args.Data.ReadByte(); int id = args.Data.ReadByte();
bool pvp = args.Data.ReadBoolean(); bool pvp = args.Data.ReadBoolean();
args.TPlayer.hostile = pvp; long seconds = (long)(DateTime.UtcNow - args.Player.LastPvpChange).TotalSeconds;
if (id != args.Player.Index) if (ConfigurationManager.PvpThrottle > 0 && seconds < ConfigurationManager.PvpThrottle)
args.TPlayer.hostile = true; {
if (ConfigurationManager.PermaPvp) args.Player.SendMessage(string.Format("You cannot change pvp status for {0} seconds", ConfigurationManager.PvpThrottle - seconds), 255, 0, 0);
args.TPlayer.hostile = true; args.Player.SetPvP(id != args.Player.Index || ConfigurationManager.PermaPvp ? true : args.TPlayer.hostile);
NetMessage.SendData(30, -1, -1, "", args.Player.Index); }
else
{
args.Player.SetPvP(id != args.Player.Index || ConfigurationManager.PermaPvp ? true : pvp);
}
return true; return true;
} }
@ -284,6 +314,7 @@ namespace TShockAPI
{ {
return Tools.HandleGriefer(args.Player, "Update Player abuse"); return Tools.HandleGriefer(args.Player, "Update Player abuse");
} }
return false; return false;
} }
@ -302,7 +333,16 @@ namespace TShockAPI
if (type == 29 || type == 28 || type == 37) if (type == 29 || type == 28 || type == 37)
{ {
Log.Debug(string.Format("Explosive(PlyXY:{0}_{1}, Type:{2})", args.Player.TileX, args.Player.TileY, type)); 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."); 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; return false;
} }
@ -310,10 +350,6 @@ namespace TShockAPI
private static bool HandlePlayerKillMe(GetDataHandlerArgs args) private static bool HandlePlayerKillMe(GetDataHandlerArgs args)
{ {
byte id = args.Data.ReadInt8(); 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) if (id != args.Player.Index)
{ {
return Tools.HandleGriefer(args.Player, "Trying to execute KillMe on someone else."); return Tools.HandleGriefer(args.Player, "Trying to execute KillMe on someone else.");
@ -324,10 +360,6 @@ namespace TShockAPI
private static bool HandlePlayerDamage(GetDataHandlerArgs args) private static bool HandlePlayerDamage(GetDataHandlerArgs args)
{ {
byte playerid = args.Data.ReadInt8(); 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; return !TShock.Players[playerid].TPlayer.hostile;
} }
@ -361,14 +393,14 @@ namespace TShockAPI
{ {
args.Player.SendMessage("You do not have permission to use lava", Color.Red); 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); 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 args.Player.SendTileSquare(x, y);
return true; return true;
} }
if (!lava && !args.Player.Group.HasPermission("canwater")) if (!lava && !args.Player.Group.HasPermission("canwater"))
{ {
args.Player.SendMessage("You do not have permission to use water", Color.Red); 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); 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 args.Player.SendTileSquare(x, y);
return true; return true;
} }
@ -382,11 +414,7 @@ namespace TShockAPI
if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32))) 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})", Log.Debug(string.Format("Liquid(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Amount:{6})",
plyX, plyY, plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid));
tileX, tileY,
Math.Abs(plyX - tileX), Math.Abs(plyY - tileY),
liquid
));
return Tools.HandleGriefer(args.Player, "Placing impossible to place liquid."); ; return Tools.HandleGriefer(args.Player, "Placing impossible to place liquid."); ;
} }
@ -398,7 +426,7 @@ namespace TShockAPI
if (flag) if (flag)
{ {
args.Player.SendMessage("The spawn is protected!", Color.Red); args.Player.SendMessage("The spawn is protected!", Color.Red);
// TODO need to revert player changes so they are insync with server args.Player.SendTileSquare(x, y);
return true; return true;
} }
} }
@ -422,5 +450,32 @@ namespace TShockAPI
} }
return false; 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
View 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;
}
}
}

View file

@ -53,24 +53,6 @@ namespace TShockAPI
_logWriter = new StreamWriter(filename, !clear); _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> /// <summary>
/// Checks whether the log level contains the specified flag. /// Checks whether the log level contains the specified flag.
/// </summary> /// </summary>
@ -116,6 +98,16 @@ namespace TShockAPI
Write(message, LogLevel.Info); 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> /// <summary>
/// Writes a debug string to the log file. /// Writes a debug string to the log file.
/// </summary> /// </summary>
@ -124,5 +116,31 @@ namespace TShockAPI
{ {
Write(message, LogLevel.Debug); 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();
}
} }
} }

View file

@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyVersion("2.3.0.0627")]
[assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyFileVersion("2.3.0.0627")]

307
TShockAPI/RegionManager.cs Normal file
View 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;
}
}
}

View 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;
}
}
}

View file

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // 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 // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
@ -71,9 +71,9 @@ namespace TShockAPI {
///#ALWAYS DECLARE A GROUP&apos;S PARENT BEFORE YOU DECLARE THE GROUP ///#ALWAYS DECLARE A GROUP&apos;S PARENT BEFORE YOU DECLARE THE GROUP
/// ///
///#currently avaliable permissions: ///#currently avaliable permissions:
///#kick ban ignorecheatdetection ///#reservedslot - reserved slot for player
///#maintenance cfg causeevents spawnboss tp ///#canwater - allow players to use water
///#spawnmob che [rest of string was truncated]&quot;;. ///#canlav [rest of string was truncated]&quot;;.
/// </summary> /// </summary>
internal static string groups { internal static string groups {
get { 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> /// <summary>
/// Looks up a localized string similar to #format /// Looks up a localized string similar to #format
///#ip group ///#ip group

View file

@ -1,21 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?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> <root>
<!-- <!--
Microsoft ResX Schema 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"> <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> <value>config\groups.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data> </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"> <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> <value>config\users.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data> </data>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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();
}
}
}

View file

@ -19,20 +19,27 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Terraria; using Terraria;
using TerrariaAPI;
namespace TShockAPI namespace TShockAPI
{ {
public class TSPlayer 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 static readonly TSPlayer All = new TSPlayer("All");
public uint TileThreshold { get; set; } public int TileThreshold { get; set; }
public Dictionary<Vector2, Tile> TilesDestroyed { get; set; } public Dictionary<Vector2, Tile> TilesDestroyed { get; protected set; }
public bool SyncHP { get; set; } public bool SyncHP { get; set; }
public bool SyncMP { get; set; } public bool SyncMP { get; set; }
public Group Group { get; set; } public Group Group { get; set; }
public bool ReceivedInfo { get; set; } public bool ReceivedInfo { get; set; }
public int Index { get; protected 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 public bool RealPlayer
{ {
get { return Index >= 0 && Index < Main.maxNetPlayers; } 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; } 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> /// <summary>
/// Terraria Player /// Terraria Player
/// </summary> /// </summary>
@ -49,13 +63,6 @@ namespace TShockAPI
{ {
get { return TPlayer.name; } get { return TPlayer.name; }
} }
public string IP
{
get
{
return RealPlayer ? Tools.GetRealIP(Netplay.serverSock[Index].tcpClient.Client.RemoteEndPoint.ToString()) : "";
}
}
public bool Active public bool Active
{ {
get { return TPlayer.active; } get { return TPlayer.active; }
@ -87,6 +94,25 @@ namespace TShockAPI
{ {
get { return (int)(Y / 16); } 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) public TSPlayer(int index)
{ {
@ -104,6 +130,62 @@ namespace TShockAPI
Group = new Group("null"); 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) public virtual void SendMessage(string msg)
{ {
SendMessage(msg, 0, 255, 0); SendMessage(msg, 0, 255, 0);
@ -116,30 +198,104 @@ namespace TShockAPI
public virtual void SendMessage(string msg, byte red, byte green, byte blue) 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 TSServerPlayer : TSPlayer
public class ServerPlayer : TSPlayer
{ {
public ServerPlayer() : base("Server") public TSServerPlayer() : base("Server")
{ {
Group = new SuperAdminGroup(); Group = new SuperAdminGroup();
} }
public override void SendMessage(string msg) public override void SendMessage(string msg)
{ {
Console.WriteLine(msg); SendMessage(msg, 0, 255, 0);
}
public override void SendMessage(string msg, byte red, byte green, byte blue)
{
SendMessage(msg);
} }
public override void SendMessage(string msg, Color color) 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);
}
} }
} }
} }

View file

@ -17,29 +17,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Reflection;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Content;
using Terraria; using Terraria;
using TerrariaAPI; using TerrariaAPI;
using TerrariaAPI.Hooks; using TerrariaAPI.Hooks;
using System.Text;
namespace TShockAPI namespace TShockAPI
{ {
[APIVersion(1, 3)] [APIVersion(1, 5)]
public class TShock : TerrariaPlugin 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 string SavePath = "tshock";
public static readonly Version VersionNum = new Version(2, 1, 0, 6); public static TSPlayer[] Players = new TSPlayer[Main.maxPlayers];
public static readonly string VersionCodename = "Forgot to increase the version.";
public static BanManager Bans = new BanManager(Path.Combine(SavePath, "bans.txt")); 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 public override Version Version
{ {
@ -74,6 +76,7 @@ namespace TShockAPI
Console.WriteLine(version); Console.WriteLine(version);
Log.Initialize(Path.Combine(SavePath, "log.txt"), LogLevel.All, false); Log.Initialize(Path.Combine(SavePath, "log.txt"), LogLevel.All, false);
Log.Info(version); Log.Info(version);
Log.Info("Starting..."); Log.Info("Starting...");
@ -99,6 +102,18 @@ namespace TShockAPI
Commands.InitCommands(); Commands.InitCommands();
Log.Info("Commands initialized"); 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()); HandleCommandLine(Environment.GetCommandLineArgs());
} }
@ -176,17 +191,19 @@ namespace TShockAPI
private void OnUpdate(GameTime time) private void OnUpdate(GameTime time)
{ {
UpdateManager.UpdateProcedureCheck(); UpdateManager.UpdateProcedureCheck();
if (Backups.IsBackupTime)
Backups.Backup();
foreach (TSPlayer player in TShock.Players) foreach (TSPlayer player in TShock.Players)
{ {
if (player != null && player.Active) if (player != null && player.Active)
{ {
if (player.TileThreshold >= 20) if (player.TileThreshold >= ConfigurationManager.TileThreshold)
{ {
if (Tools.HandleTntUser(player, "Kill tile abuse detected.")) if (Tools.HandleTntUser(player, "Kill tile abuse detected."))
{ {
RevertKillTile(player); TSPlayer.Server.RevertKillTile(player.TilesDestroyed);
player.TileThreshold = 0;
player.TilesDestroyed.Clear();
} }
else if (player.TileThreshold > 0) else if (player.TileThreshold > 0)
{ {
@ -198,6 +215,20 @@ namespace TShockAPI
else if (player.TileThreshold > 0) else if (player.TileThreshold > 0)
{ {
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); var player = new TSPlayer(ply);
player.Group = Tools.GetGroupForIP(player.IP); player.Group = Tools.GetGroupForIP(player.IP);
if (Tools.ActivePlayers() + 1 > ConfigurationManager.MaxSlots && if (Tools.ActivePlayers() + 1 > ConfigurationManager.MaxSlots && !player.Group.HasPermission("reservedslot"))
!player.Group.HasPermission("reservedslot"))
{ {
Tools.ForceKick(player, "Server is full"); Tools.ForceKick(player, "Server is full");
handler.Handled = true; handler.Handled = true;
@ -233,7 +263,9 @@ namespace TShockAPI
} }
Players[ply] = player; Players[ply] = player;
Netplay.serverSock[ply].spamCheck = ConfigurationManager.SpamChecks; Players[ply].InitSpawn = false;
Netplay.spamCheck = ConfigurationManager.SpamChecks;
} }
private void OnLeave(int ply) private void OnLeave(int ply)
@ -245,12 +277,18 @@ namespace TShockAPI
if (tsplr != null && tsplr.ReceivedInfo) if (tsplr != null && tsplr.ReceivedInfo)
Log.Info(string.Format("{0} left.", tsplr.Name)); 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; Players[ply] = null;
} }
private void OnChat(messageBuffer msg, int ply, string text, HandledEventArgs e) private void OnChat(messageBuffer msg, int ply, string text, HandledEventArgs e)
{ {
if (Main.netMode != 2) if (Main.netMode != 2 || e.Handled)
return; return;
if (msg.whoAmI != ply) if (msg.whoAmI != ply)
@ -287,6 +325,9 @@ namespace TShockAPI
/// <param name="e"></param> /// <param name="e"></param>
private void ServerHooks_OnCommand(string text, HandledEventArgs e) private void ServerHooks_OnCommand(string text, HandledEventArgs e)
{ {
if (e.Handled)
return;
// Damn you ThreadStatic and Redigit // Damn you ThreadStatic and Redigit
if (Main.rand == null) if (Main.rand == null)
{ {
@ -319,6 +360,12 @@ namespace TShockAPI
{ {
Log.Info(string.Format("Server said: {0}", text.Remove(0, 4))); 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("/")) else if (text.StartsWith("/"))
{ {
if (Commands.HandleCommand(TSPlayer.Server, text)) if (Commands.HandleCommand(TSPlayer.Server, text))
@ -329,51 +376,78 @@ namespace TShockAPI
private void GetData(GetDataEventArgs e) 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]; TSPlayer player = Players[e.Msg.whoAmI];
if (!player.ConnectionAlive) if (!player.ConnectionAlive)
{
e.Handled = true;
return; return;
}
if (Main.verboseNetplay) 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)) try
e.Handled = true; {
} if (GetDataHandlers.HandlerGetData(type, player, data))
catch (Exception ex) e.Handled = true;
{ }
Log.Error(ex.ToString()); catch (Exception ex)
{
Log.Error(ex.ToString());
}
} }
} }
} }
private void OnGreetPlayer(int who, HandledEventArgs e) private void OnGreetPlayer(int who, HandledEventArgs e)
{ {
if (Main.netMode != 2) if (Main.netMode != 2 || e.Handled)
return; return;
TSPlayer player = Players[who]; TSPlayer player = Players[who];
Log.Info(string.Format("{0} ({1}) from '{2}' group joined.", player.Name, player.IP, player.Group.Name)); Log.Info(string.Format("{0} ({1}) from '{2}' group joined.", player.Name, player.IP, player.Group.Name));
Tools.ShowFileToUser(player, "motd.txt"); Tools.ShowFileToUser(player, "motd.txt");
if (HackedHealth(who)) if (HackedHealth(player))
{ {
Tools.HandleCheater(player, "Hacked health."); Tools.HandleCheater(player, "Hacked health.");
} }
if (ConfigurationManager.PermaPvp) if (ConfigurationManager.PermaPvp)
{ {
Main.player[who].hostile = true; player.SetPvP(true);
NetMessage.SendData(30, -1, -1, "", who);
} }
if (Players[who].Group.HasPermission("causeevents") && ConfigurationManager.InfiniteInvasion) if (Players[who].Group.HasPermission("causeevents") && ConfigurationManager.InfiniteInvasion)
{ {
StartInvasion(); 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; e.Handled = true;
} }
@ -393,24 +467,6 @@ namespace TShockAPI
* Useful stuff: * 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() public static void StartInvasion()
{ {
Main.invasionType = 1; 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) public static bool CheckSpawn(int x, int y)
{ {
Vector2 tile = new Vector2(x, y); Vector2 tile = new Vector2(x, y);
@ -545,25 +532,12 @@ namespace TShockAPI
return true; return true;
} }
public static void RevertKillTile(TSPlayer player) public static bool HackedHealth(TSPlayer player)
{ {
Tile[] tiles = new Tile[player.TilesDestroyed.Count]; return (player.TPlayer.statManaMax > 200) ||
player.TilesDestroyed.Values.CopyTo(tiles, 0); (player.TPlayer.statMana > 200) ||
Vector2[] positions = new Vector2[player.TilesDestroyed.Count]; (player.TPlayer.statLifeMax > 400) ||
player.TilesDestroyed.Keys.CopyTo(positions, 0); (player.TPlayer.statLife > 400);
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);
} }

View file

@ -12,6 +12,21 @@
<AssemblyName>TShockAPI</AssemblyName> <AssemblyName>TShockAPI</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <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>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -47,16 +62,19 @@
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="TerrariaServer"> <Reference Include="TerrariaServer">
<HintPath>.\TerrariaServer.exe</HintPath> <HintPath>TerrariaServerBins\TerrariaServer.exe</HintPath>
<Private>False</Private>
</Reference> </Reference>
<Reference Include="TerrariaServerAPI"> <Reference Include="TerrariaServerAPI">
<HintPath>.\TerrariaServerAPI.dll</HintPath> <HintPath>TerrariaServerBins\TerrariaServerAPI.dll</HintPath>
<Private>False</Private> </Reference>
<Reference Include="XNAHelpers">
<HintPath>TerrariaServerBins\XNAHelpers.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BackupManager.cs" />
<Compile Include="BanManager.cs" /> <Compile Include="BanManager.cs" />
<Compile Include="ItemManager.cs" />
<Compile Include="Commands.cs" /> <Compile Include="Commands.cs" />
<Compile Include="ConfigFile.cs" /> <Compile Include="ConfigFile.cs" />
<Compile Include="ConfigurationManager.cs" /> <Compile Include="ConfigurationManager.cs" />
@ -64,17 +82,19 @@
<Compile Include="GetDataHandlers.cs" /> <Compile Include="GetDataHandlers.cs" />
<Compile Include="Group.cs" /> <Compile Include="Group.cs" />
<Compile Include="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="RegionManager.cs" />
<Compile Include="RememberPosManager.cs" />
<Compile Include="Resources.Designer.cs"> <Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="StreamExt.cs" />
<Compile Include="Tools.cs" /> <Compile Include="Tools.cs" />
<Compile Include="TShock.cs" /> <Compile Include="TShock.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TSPlayer.cs" /> <Compile Include="TSPlayer.cs" />
<Compile Include="UpdateManager.cs" /> <Compile Include="UpdateManager.cs" />
<Compile Include="WarpsManager.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="config\groups.txt" /> <None Include="config\groups.txt" />
@ -89,14 +109,45 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </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" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PreBuildEvent> <PreBuildEvent>
</PreBuildEvent> </PreBuildEvent>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PostBuildEvent>"$(SolutionDir)\myass.bat"</PostBuildEvent> <PostBuildEvent>
</PostBuildEvent>
</PropertyGroup> </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. <!-- 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. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -19,20 +19,15 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Net;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Terraria; using Terraria;
namespace TShockAPI namespace TShockAPI
{ {
internal enum NPCList
{
WORLD_EATER = 0,
EYE = 1,
SKELETRON = 2
}
internal class Tools internal class Tools
{ {
private static Random random = new Random();
private static List<Group> groups = new List<Group>(); private static List<Group> groups = new List<Group>();
/// <summary> /// <summary>
@ -66,6 +61,25 @@ namespace TShockAPI
return sb.ToString(); 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> /// <summary>
/// It's a clamp function /// It's a clamp function
/// </summary> /// </summary>
@ -118,7 +132,7 @@ namespace TShockAPI
TSPlayer.Server.SendMessage(log, color); TSPlayer.Server.SendMessage(log, color);
foreach (TSPlayer player in TShock.Players) 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); player.SendMessage(log, color);
} }
} }
@ -163,31 +177,115 @@ namespace TShockAPI
return found; return found;
} }
/// <summary> public static void GetRandomClearTileWithInRange(int startTileX, int startTileY, int tileXRange, int tileYRange, out int tileX, out int tileY)
/// 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)
{ {
switch (type) int j = 0;
do
{ {
case NPCList.WORLD_EATER: if (j == 100)
WorldGen.shadowOrbSmashed = true; {
WorldGen.shadowOrbCount = 3; tileX = startTileX;
int w = NPC.NewNPC((int)player.X, (int)player.Y, 13, 1); tileY = startTileY;
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;
break; 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> /// <summary>
@ -201,7 +299,7 @@ namespace TShockAPI
{ {
if (player != null && player.Active) if (player != null && player.Active)
{ {
Tools.ForceKick(player, reason); ForceKick(player, reason);
} }
} }
} }
@ -215,7 +313,7 @@ namespace TShockAPI
{ {
if (!player.ConnectionAlive) if (!player.ConnectionAlive)
return; 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)); Log.Info(string.Format("{0} was force kicked for : {1}", player.IP, reason));
} }
@ -231,12 +329,12 @@ namespace TShockAPI
if (!player.Group.HasPermission("immunetokick")) if (!player.Group.HasPermission("immunetokick"))
{ {
string playerName = player.Name; 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)); Log.Info(string.Format("Kicked {0} for : {1}", playerName, reason));
if (adminUserName.Length == 0) if (adminUserName.Length == 0)
Broadcast(string.Format("{0} was kicked for {1}", playerName, reason.ToLower())); Broadcast(string.Format("{0} was kicked for {1}", playerName, reason.ToLower()));
else 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 true;
} }
return false; return false;
@ -256,12 +354,12 @@ namespace TShockAPI
string ip = player.IP; string ip = player.IP;
string playerName = player.Name; string playerName = player.Name;
TShock.Bans.AddBan(ip, playerName, reason); 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)); Log.Info(string.Format("Banned {0} for : {1}", playerName, reason));
if (adminUserName.Length == 0) if (adminUserName.Length == 0)
Broadcast(string.Format("{0} was banned for {1}", playerName, reason.ToLower())); Broadcast(string.Format("{0} was banned for {1}", playerName, reason.ToLower()));
else 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 true;
} }
return false; return false;
@ -458,13 +556,35 @@ namespace TShockAPI
{ {
continue; 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(); sr.Close();
return GetGroup("default"); 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
View 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;
}
}
}

View file

@ -8,14 +8,36 @@
#ALWAYS DECLARE A GROUP'S PARENT BEFORE YOU DECLARE THE GROUP #ALWAYS DECLARE A GROUP'S PARENT BEFORE YOU DECLARE THE GROUP
#currently avaliable permissions: #currently avaliable permissions:
#kick ban ignorecheatdetection #reservedslot - reserved slot for player
#maintenance cfg causeevents spawnboss tp #canwater - allow players to use water
#spawnmob cheat kill pvpfun #canlava - allow playes to use lava
#immunetoban immunetokick editspawn #warp - allow players to use warps
#ignoregriefdetection reservedslot #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 vip default reservedslot
newadmin default kick editspawn reservedslot newadmin default kick editspawn reservedslot
admin newadmin ban unban causeevents spawnboss spawnmob tp immunetokick kill logs admin newadmin ban unban whitelist causeevents spawnboss spawnmob managewarp time tp pvpfun kill logs immunetokick
trustedadmin admin maintenance cfg cheat pvpfun ignorecheatdetection immunetoban ignoregriefdetection trustedadmin admin maintenance cfg butcher cheat immunetoban ignorecheatdetection ignoregriefdetection usebanneditem

View 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

View file

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010 # Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockAPI", "TShockAPI\TShockAPI.csproj", "{49606449-072B-4CF5-8088-AA49DA586694}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockAPI", "TShockAPI\TShockAPI.csproj", "{49606449-072B-4CF5-8088-AA49DA586694}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update", "Update\Update.csproj", "{AF322FAB-9A32-43AA-A01A-76B2A039F711}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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.ActiveCfg = Release|Any CPU
{49606449-072B-4CF5-8088-AA49DA586694}.Release|Mixed Platforms.Build.0 = 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 {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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -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));
}
}
}

View file

@ -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")]

View file

@ -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));
}
}
}
}

View file

@ -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>

View file

@ -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>