diff --git a/GUIDELINES b/GUIDELINES
new file mode 100644
index 00000000..fd99abcf
--- /dev/null
+++ b/GUIDELINES
@@ -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/).
\ No newline at end of file
diff --git a/TShockAPI/BackupManager.cs b/TShockAPI/BackupManager.cs
new file mode 100644
index 00000000..31be1b5b
--- /dev/null
+++ b/TShockAPI/BackupManager.cs
@@ -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 .
+*/
+
+
+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();
+ }
+ }
+ }
+ }
+}
diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs
index e9853157..56d46df2 100755
--- a/TShockAPI/Commands.cs
+++ b/TShockAPI/Commands.cs
@@ -93,7 +93,7 @@ namespace TShockAPI
}
public static class Commands
{
- private static List ChatCommands = new List();
+ public static List ChatCommands = new List();
public static void InitCommands()
{
@@ -102,6 +102,7 @@ namespace TShockAPI
ChatCommands.Add(new Command("banip", "ban", BanIP));
ChatCommands.Add(new Command("unban", "unban", UnBan));
ChatCommands.Add(new Command("unbanip", "unban", UnBanIP));
+ ChatCommands.Add(new Command("whitelist", "whitelist", Whitelist));
ChatCommands.Add(new Command("off", "maintenance", Off));
ChatCommands.Add(new Command("off-nosave", "maintenance", OffNoSave));
ChatCommands.Add(new Command("checkupdates", "maintenance", CheckUpdates));
@@ -111,6 +112,7 @@ namespace TShockAPI
ChatCommands.Add(new Command("invade", "causeevents", Invade));
ChatCommands.Add(new Command("eater", "spawnboss", Eater));
ChatCommands.Add(new Command("eye", "spawnboss", Eye));
+ ChatCommands.Add(new Command("king", "spawnboss", King));
ChatCommands.Add(new Command("skeletron", "spawnboss", Skeletron));
ChatCommands.Add(new Command("hardcore", "spawnboss", Hardcore));
ChatCommands.Add(new Command("spawnmob", "spawnmob", SpawnMob));
@@ -119,16 +121,20 @@ namespace TShockAPI
ChatCommands.Add(new Command("spawn", "tp", Spawn));
ChatCommands.Add(new Command("tp", "tp", TP));
ChatCommands.Add(new Command("tphere", "tp", TPHere));
+ ChatCommands.Add(new Command("warp", "warp", UseWarp));
+ ChatCommands.Add(new Command("setwarp", "managewarp", SetWarp));
+ ChatCommands.Add(new Command("delwarp", "managewarp", DeleteWarp));
ChatCommands.Add(new Command("reload", "cfg", Reload));
ChatCommands.Add(new Command("debug-config", "cfg", DebugConfiguration));
ChatCommands.Add(new Command("password", "cfg", Password));
ChatCommands.Add(new Command("save", "cfg", Save));
ChatCommands.Add(new Command("maxspawns", "cfg", MaxSpawns));
ChatCommands.Add(new Command("spawnrate", "cfg", SpawnRate));
- ChatCommands.Add(new Command("time", "cfg", Time));
+ ChatCommands.Add(new Command("time", "time", Time));
ChatCommands.Add(new Command("slap", "pvpfun", Slap));
ChatCommands.Add(new Command("antibuild", "editspawn", ToggleAntiBuild));
ChatCommands.Add(new Command("protectspawn", "editspawn", ProtectSpawn));
+ ChatCommands.Add(new Command("region", "editspawn", Region));
ChatCommands.Add(new Command("help", "", Help));
ChatCommands.Add(new Command("playing", "", Playing));
ChatCommands.Add(new Command("online", "", Playing));
@@ -137,10 +143,11 @@ namespace TShockAPI
ChatCommands.Add(new Command("me", "", ThirdPerson));
ChatCommands.Add(new Command("p", "", PartyChat));
ChatCommands.Add(new Command("rules", "", Rules));
+ ChatCommands.Add(new Command("displaylogs", "logs", Rules));
if (ConfigurationManager.DistributationAgent != "terraria-online")
{
ChatCommands.Add(new Command("kill", "kill", Kill));
- ChatCommands.Add(new Command("butcher", "cheat", Butcher));
+ ChatCommands.Add(new Command("butcher", "butcher", Butcher));
ChatCommands.Add(new Command("i", "cheat", Item));
ChatCommands.Add(new Command("item", "cheat", Item));
ChatCommands.Add(new Command("give", "cheat", Give));
@@ -175,20 +182,18 @@ namespace TShockAPI
if (cmd == null)
{
- player.SendMessage("That command does not exist, try /help", Color.Red);
+ return false;
+ }
+
+ if (!cmd.CanRun(player))
+ {
+ Tools.SendLogs(string.Format("{0} tried to execute {1}", player.Name, cmd.Name), Color.Red);
+ player.SendMessage("You do not have access to that command.", Color.Red);
}
else
{
- if (!cmd.CanRun(player))
- {
- Tools.SendLogs(string.Format("{0} tried to execute {1}", player.Name, cmd.Name), Color.Red);
- player.SendMessage("You do not have access to that command.", Color.Red);
- }
- else
- {
- Tools.SendLogs(string.Format("{0} executed: /{1}", player.Name, cmdText), Color.Red);
- cmd.Run(cmdText, player, args);
- }
+ Tools.SendLogs(string.Format("{0} executed: /{1}", player.Name, cmdText), Color.Red);
+ cmd.Run(cmdText, player, args);
}
return true;
}
@@ -291,19 +296,19 @@ namespace TShockAPI
}
string plStr = args.Parameters[0];
- var player = Tools.FindPlayer(plStr);
- if (player.Count == 0)
+ var players = Tools.FindPlayer(plStr);
+ if (players.Count == 0)
{
args.Player.SendMessage("Invalid player!", Color.Red);
}
- else if (player.Count > 1)
+ else if (players.Count > 1)
{
args.Player.SendMessage("More than one player matched!", Color.Red);
}
else
{
string reason = args.Parameters.Count > 1 ? String.Join(" ", args.Parameters.GetRange(1, args.Parameters.Count - 1)) : "Misbehaviour.";
- if (!Tools.Kick(player[0], reason))
+ if (!Tools.Kick(players[0], reason))
{
args.Player.SendMessage("You can't kick another admin!", Color.Red);
}
@@ -324,19 +329,19 @@ namespace TShockAPI
}
string plStr = args.Parameters[0];
- var player = Tools.FindPlayer(plStr);
- if (player.Count == 0)
+ var players = Tools.FindPlayer(plStr);
+ if (players.Count == 0)
{
args.Player.SendMessage("Invalid player!", Color.Red);
}
- else if (player.Count > 1)
+ else if (players.Count > 1)
{
args.Player.SendMessage("More than one player matched!", Color.Red);
}
else
{
string reason = args.Parameters.Count > 1 ? String.Join(" ", args.Parameters.GetRange(1, args.Parameters.Count - 1)) : "Misbehaviour.";
- if (!Tools.Ban(player[0], reason))
+ if (!Tools.Ban(players[0], reason))
{
args.Player.SendMessage("You can't ban another admin!", Color.Red);
}
@@ -413,6 +418,23 @@ namespace TShockAPI
}
}
+ public static void Whitelist(CommandArgs args)
+ {
+ if (args.Parameters.Count == 1)
+ {
+ TextWriter tw = new StreamWriter(FileTools.WhitelistPath, true);
+ tw.WriteLine(args.Parameters[0]);
+ tw.Close();
+ args.Player.SendMessage("Added " + args.Parameters[0] + " to the whitelist.");
+ }
+ }
+
+ public static void DisplayLogs(CommandArgs args)
+ {
+ args.Player.DisplayLogs = (!args.Player.DisplayLogs);
+ args.Player.SendMessage("You now " + (args.Player.DisplayLogs ? "receive" : "stopped receiving") + " logs");
+ }
+
#endregion Player Management Commands
#region Server Maintenence Commands
@@ -490,12 +512,8 @@ namespace TShockAPI
private static void Bloodmoon(CommandArgs args)
{
+ TSPlayer.Server.SetBloodMoon(true);
Tools.Broadcast(string.Format("{0} turned on blood moon.", args.Player.Name));
- Main.bloodMoon = true;
- Main.time = 0;
- Main.dayTime = false;
- NetMessage.SendData(18, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
- NetMessage.syncPlayers();
}
private static void Invade(CommandArgs args)
@@ -514,29 +532,101 @@ namespace TShockAPI
private static void Eater(CommandArgs args)
{
- Tools.NewNPC(NPCList.WORLD_EATER, args.Player);
- Tools.Broadcast(string.Format("{0} has spawned an eater of worlds!", args.Player.Name));
+ if (args.Parameters.Count > 1)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /eater [amount]", Color.Red);
+ return;
+ }
+ int amount = 1;
+ if (args.Parameters.Count == 1 && !int.TryParse(args.Parameters[0], out amount))
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /eater [amount]", Color.Red);
+ return;
+ }
+ NPC eater = Tools.GetNPCById(13);
+ TSPlayer.Server.SpawnNPC(eater.type, eater.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
+ Tools.Broadcast(string.Format("{0} has spawned eater of worlds {1} times!", args.Player.Name, amount));
}
private static void Eye(CommandArgs args)
{
- Tools.NewNPC(NPCList.EYE, args.Player);
- Tools.Broadcast(string.Format("{0} has spawned an eye!", args.Player.Name));
+ if (args.Parameters.Count > 1)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /eye [amount]", Color.Red);
+ return;
+ }
+ int amount = 1;
+ if (args.Parameters.Count == 1 && !int.TryParse(args.Parameters[0], out amount))
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /eye [amount]", Color.Red);
+ return;
+ }
+ NPC eye = Tools.GetNPCById(4);
+ TSPlayer.Server.SetTime(false, 0.0);
+ TSPlayer.Server.SpawnNPC(eye.type, eye.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
+ Tools.Broadcast(string.Format("{0} has spawned eye {1} times!", args.Player.Name, amount));
+ }
+
+ private static void King(CommandArgs args)
+ {
+ if (args.Parameters.Count > 1)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /king [amount]", Color.Red);
+ return;
+ }
+ int amount = 1;
+ if (args.Parameters.Count == 1 && !int.TryParse(args.Parameters[0], out amount))
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /king [amount]", Color.Red);
+ return;
+ }
+ NPC king = Tools.GetNPCById(50);
+ TSPlayer.Server.SpawnNPC(king.type, king.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
+ Tools.Broadcast(string.Format("{0} has spawned king slime {1} times!", args.Player.Name, amount));
}
private static void Skeletron(CommandArgs args)
{
- Tools.NewNPC(NPCList.SKELETRON, args.Player);
- Tools.Broadcast(string.Format("{0} has spawned skeletron!", args.Player.Name));
+ if (args.Parameters.Count > 1)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /skeletron [amount]", Color.Red);
+ return;
+ }
+ int amount = 1;
+ if (args.Parameters.Count == 1 && !int.TryParse(args.Parameters[0], out amount))
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /skeletron [amount]", Color.Red);
+ return;
+ }
+ NPC skeletron = Tools.GetNPCById(35);
+ TSPlayer.Server.SetTime(false, 0.0);
+ TSPlayer.Server.SpawnNPC(skeletron.type, skeletron.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
+ Tools.Broadcast(string.Format("{0} has spawned skeletron {1} times!", args.Player.Name, amount));
}
private static void Hardcore(CommandArgs args)
{
- foreach (NPCList type in Enum.GetValues(typeof(NPCList)))
+ if (args.Parameters.Count > 1)
{
- Tools.NewNPC(type, args.Player);
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /hardcore [amount]", Color.Red);
+ return;
}
- Tools.Broadcast(string.Format("{0} has spawned all bosses!", args.Player.Name));
+ int amount = 1;
+ if (args.Parameters.Count == 1 && !int.TryParse(args.Parameters[0], out amount))
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /hardcore [amount]", Color.Red);
+ return;
+ }
+ NPC eater = Tools.GetNPCById(13);
+ NPC eye = Tools.GetNPCById(4);
+ NPC king = Tools.GetNPCById(50);
+ NPC skeletron = Tools.GetNPCById(35);
+ TSPlayer.Server.SetTime(false, 0.0);
+ TSPlayer.Server.SpawnNPC(eater.type, eater.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
+ TSPlayer.Server.SpawnNPC(eye.type, eye.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
+ TSPlayer.Server.SpawnNPC(king.type, king.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
+ TSPlayer.Server.SpawnNPC(skeletron.type, skeletron.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
+ Tools.Broadcast(string.Format("{0} has spawned all bosses {1} times!", args.Player.Name, amount));
}
private static void SpawnMob(CommandArgs args)
@@ -551,27 +641,33 @@ namespace TShockAPI
args.Player.SendMessage("Missing mob name/id", Color.Red);
return;
}
-
- int type = -1;
int amount = 1;
-
- if (!int.TryParse(args.Parameters[0], out type))
- type = TShock.GetNPCID(args.Parameters[0]);
if (args.Parameters.Count == 2 && !int.TryParse(args.Parameters[1], out amount))
{
args.Player.SendMessage("Invalid syntax! Proper syntax: /spawnmob [amount]", Color.Red);
return;
}
- if (type >= 1 && type < Main.maxNPCTypes)
+ var npcs = Tools.GetNPCByIdOrName(args.Parameters[0]);
+ if (npcs.Count == 0)
{
- int npcid = -1;
- for (int i = 0; i < amount; i++)
- npcid = NPC.NewNPC((int)args.Player.X, (int)args.Player.Y, type, 0);
- Tools.Broadcast(string.Format("{0} was spawned {1} time(s).", Main.npc[npcid].name, amount));
+ args.Player.SendMessage("Invalid mob type!", Color.Red);
+ }
+ else if (npcs.Count > 1)
+ {
+ args.Player.SendMessage(string.Format("More than one ({0}) mob matched!", npcs.Count), Color.Red);
}
else
- args.Player.SendMessage("Invalid mob type!", Color.Red);
+ {
+ var npc = npcs[0];
+ if (npc.type >= 1 && npc.type < Main.maxNPCTypes)
+ {
+ TSPlayer.Server.SpawnNPC(npc.type, npc.name, amount, (int)args.Player.TileX, (int)args.Player.TileY, 50, 20);
+ Tools.Broadcast(string.Format("{0} was spawned {1} time(s).", npc.name, amount));
+ }
+ else
+ args.Player.SendMessage("Invalid mob type!", Color.Red);
+ }
}
#endregion Cause Events and Spawn Monsters Commands
@@ -580,20 +676,38 @@ namespace TShockAPI
private static void Home(CommandArgs args)
{
- TShock.Teleport(args.Player.Index, args.TPlayer.SpawnX * 16 + 8 - args.TPlayer.width / 2,
- args.TPlayer.SpawnY * 16 - args.TPlayer.height);
+ if (!args.Player.RealPlayer)
+ {
+ args.Player.SendMessage("You cannot use teleport commands!");
+ return;
+ }
+
+ args.Player.Spawn();
args.Player.SendMessage("Teleported to your spawnpoint.");
}
private static void Spawn(CommandArgs args)
{
- TShock.Teleport(args.Player.Index, Main.spawnTileX * 16 + 8 - args.TPlayer.width / 2,
- Main.spawnTileY * 16 - args.TPlayer.height);
- args.Player.SendMessage("Teleported to the map's spawnpoint.");
+ if (!args.Player.RealPlayer)
+ {
+ args.Player.SendMessage("You cannot use teleport commands!");
+ return;
+ }
+
+ if (args.Player.Teleport(Main.spawnTileX, Main.spawnTileY))
+ args.Player.SendMessage("Teleported to the map's spawnpoint.");
+ else
+ args.Player.SendMessage("Teleport unavailable - Spawn point set to Bed. To unset, destroy Bed and suicide at least once.", Color.Red);
}
private static void TP(CommandArgs args)
{
+ if (!args.Player.RealPlayer)
+ {
+ args.Player.SendMessage("You cannot use teleport commands!");
+ return;
+ }
+
if (args.Parameters.Count < 1)
{
args.Player.SendMessage("Invalid syntax! Proper syntax: /tp ", Color.Red);
@@ -601,21 +715,29 @@ namespace TShockAPI
}
string plStr = String.Join(" ", args.Parameters);
- var player = Tools.FindPlayer(plStr);
- if (player.Count == 0)
+ var players = Tools.FindPlayer(plStr);
+ if (players.Count == 0)
args.Player.SendMessage("Invalid player!", Color.Red);
- else if (player.Count > 1)
+ else if (players.Count > 1)
args.Player.SendMessage("More than one player matched!", Color.Red);
else
{
- var plr = player[0];
- TShock.Teleport(args.Player.Index, plr.X, plr.Y);
- args.Player.SendMessage(string.Format("Teleported to {0}", plr.Name));
+ var plr = players[0];
+ if (args.Player.Teleport(plr.TileX, plr.TileY + 3))
+ args.Player.SendMessage(string.Format("Teleported to {0}", plr.Name));
+ else
+ args.Player.SendMessage("Teleport unavailable - Spawn point set to Bed. To unset, destroy Bed and suicide at least once.", Color.Red);
}
}
private static void TPHere(CommandArgs args)
{
+ if (!args.Player.RealPlayer)
+ {
+ args.Player.SendMessage("You cannot use teleport commands!");
+ return;
+ }
+
if (args.Parameters.Count < 1)
{
args.Player.SendMessage("Invalid syntax! Proper syntax: /tphere ", Color.Red);
@@ -623,24 +745,126 @@ namespace TShockAPI
}
string plStr = String.Join(" ", args.Parameters);
- var player = Tools.FindPlayer(plStr);
- if (player.Count == 0)
+ var players = Tools.FindPlayer(plStr);
+ if (players.Count == 0)
{
args.Player.SendMessage("Invalid player!", Color.Red);
}
- else if (player.Count > 1)
+ else if (players.Count > 1)
{
args.Player.SendMessage("More than one player matched!", Color.Red);
}
else
{
- var plr = player[0];
- TShock.Teleport(plr.Index, args.Player.X, args.Player.Y);
- plr.SendMessage(string.Format("You were teleported to {0}.", plr.Name));
- args.Player.SendMessage(string.Format("You brought {0} here.", plr.Name));
+ var plr = players[0];
+ if (plr.Teleport(args.Player.TileX, args.Player.TileY + 3))
+ {
+ plr.SendMessage(string.Format("You were teleported to {0}.", plr.Name));
+ args.Player.SendMessage(string.Format("You brought {0} here.", plr.Name));
+ }
+ else
+ args.Player.SendMessage("Teleport unavailable - Target player has spawn point set to Bed.", Color.Red);
+
}
}
+ private static void SetWarp(CommandArgs args)
+ {
+ if (args.Parameters.Count > 0)
+ {
+ string warpName = String.Join(" ", args.Parameters);
+ if (warpName.Equals("list"))
+ {
+ args.Player.SendMessage("Name reserved, use a different name", Color.Red);
+ }
+ else if (WarpsManager.AddWarp(args.Player.TileX, args.Player.TileY, warpName, Main.worldName))
+ {
+ args.Player.SendMessage("Set warp " + warpName, Color.Yellow);
+ WarpsManager.WriteSettings();
+ }
+ else
+ {
+ args.Player.SendMessage("Warp " + warpName + " already exists", Color.Red);
+ }
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /setwarp [name]", Color.Red);
+ }
+
+ private static void DeleteWarp(CommandArgs args)
+ {
+ if (args.Parameters.Count > 0)
+ {
+ string warpName = String.Join(" ", args.Parameters);
+ if (WarpsManager.DeleteWarp(warpName))
+ args.Player.SendMessage("Deleted warp " + warpName, Color.Yellow);
+ else
+ args.Player.SendMessage("Could not find specified warp", Color.Red);
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /delwarp [name]", Color.Red);
+ }
+
+ private static void UseWarp(CommandArgs args)
+ {
+ if (args.Parameters.Count > 0)
+ {
+ if (args.Parameters[0].Equals("list"))
+ {
+ args.Player.SendMessage("Current Warps:", Color.Green);
+ int page = 1;
+ if (args.Parameters.Count > 1)
+ int.TryParse(args.Parameters[1], out page);
+ var sb = new StringBuilder();
+ if (WarpsManager.Warps.Count > (15 * (page - 1)))
+ {
+ for (int j = (15 * (page - 1)); j < (15 * page); j++)
+ {
+ if (WarpsManager.Warps[j].WorldWarpName == Main.worldName)
+ {
+ if (sb.Length != 0)
+ sb.Append(", ");
+ sb.Append("/").Append(WarpsManager.Warps[j].WarpName);
+ if (j == WarpsManager.Warps.Count - 1)
+ {
+ args.Player.SendMessage(sb.ToString(), Color.Yellow);
+ break;
+ }
+ if ((j + 1) % 5 == 0)
+ {
+ args.Player.SendMessage(sb.ToString(), Color.Yellow);
+ sb.Clear();
+ }
+ }
+ }
+ }
+ if (WarpsManager.Warps.Count > (15 * page))
+ {
+ args.Player.SendMessage(string.Format("Type /warp list {0} for more warps.", (page + 1)), Color.Yellow);
+ }
+ }
+ else
+ {
+ string warpName = String.Join(" ", args.Parameters);
+ var warp = WarpsManager.FindWarp(warpName);
+ if (warp != Vector2.Zero)
+ {
+ if (args.Player.Teleport((int)warp.X, (int)warp.Y + 3))
+ args.Player.SendMessage("Warped to " + warpName, Color.Yellow);
+ else
+ args.Player.SendMessage("Warp unavailable - Spawn point set to Bed. To unset, destroy Bed and suicide at least once.", Color.Red);
+
+ }
+ else
+ {
+ args.Player.SendMessage("Specified warp not found", Color.Red);
+ }
+ }
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /warp [name] or warp list", Color.Red);
+ }
+
#endregion Teleport Commands
#region Server Config Commands
@@ -675,7 +899,12 @@ namespace TShockAPI
private static void Password(CommandArgs args)
{
- string passwd = args.Message.Remove(0, 9).Trim();
+ if (args.Parameters.Count != 1)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /password \"\"", Color.Red);
+ return;
+ }
+ string passwd = args.Parameters[0];
Netplay.password = passwd;
args.Player.SendMessage(string.Format("Server password changed to: {0}", passwd));
}
@@ -717,6 +946,10 @@ namespace TShockAPI
Tools.Broadcast(string.Format("{0} changed the spawn rate to: {1}", args.Player.Name, amount));
}
+ #endregion Server Config Commands
+
+ #region Time/PvpFun Commands
+
private static void Time(CommandArgs args)
{
if (args.Parameters.Count != 1)
@@ -728,38 +961,23 @@ namespace TShockAPI
switch (args.Parameters[0])
{
case "day":
- Main.time = 0;
- Main.dayTime = true;
- NetMessage.SendData(18, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
- NetMessage.syncPlayers();
+ TSPlayer.Server.SetTime(true, 0.0);
Tools.Broadcast(string.Format("{0} set time to day.", args.Player.Name));
break;
case "night":
- Main.time = 0;
- Main.dayTime = false;
- NetMessage.SendData(18, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
- NetMessage.syncPlayers();
+ TSPlayer.Server.SetTime(false, 0.0);
Tools.Broadcast(string.Format("{0} set time to night.", args.Player.Name));
break;
case "dusk":
- Main.dayTime = false;
- Main.time = 0.0;
- NetMessage.SendData(18, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
- NetMessage.syncPlayers();
+ TSPlayer.Server.SetTime(false, 0.0);
Tools.Broadcast(string.Format("{0} set time to dusk.", args.Player.Name));
break;
case "noon":
- Main.dayTime = true;
- Main.time = 27000.0;
- NetMessage.SendData(18, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
- NetMessage.syncPlayers();
+ TSPlayer.Server.SetTime(true, 27000.0);
Tools.Broadcast(string.Format("{0} set time to noon.", args.Player.Name));
break;
case "midnight":
- Main.dayTime = false;
- Main.time = 16200.0;
- NetMessage.SendData(18, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
- NetMessage.syncPlayers();
+ TSPlayer.Server.SetTime(false, 16200.0);
Tools.Broadcast(string.Format("{0} set time to midnight.", args.Player.Name));
break;
default:
@@ -768,7 +986,44 @@ namespace TShockAPI
}
}
- #endregion Server Config Commands
+ private static void Slap(CommandArgs args)
+ {
+ if (args.Parameters.Count < 1 || args.Parameters.Count > 2)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /slap [dmg]", Color.Red);
+ return;
+ }
+ if (args.Parameters[0].Length == 0)
+ {
+ args.Player.SendMessage("Missing player name", Color.Red);
+ return;
+ }
+
+ string plStr = args.Parameters[0];
+ var players = Tools.FindPlayer(plStr);
+ if (players.Count == 0)
+ {
+ args.Player.SendMessage("Invalid player!", Color.Red);
+ }
+ else if (players.Count > 1)
+ {
+ args.Player.SendMessage("More than one player matched!", Color.Red);
+ }
+ else
+ {
+ var plr = players[0];
+ int damage = 5;
+ if (args.Parameters.Count == 2)
+ {
+ int.TryParse(args.Parameters[1], out damage);
+ }
+ plr.DamagePlayer(damage);
+ Tools.Broadcast(string.Format("{0} slapped {1} for {2} damage.",
+ args.Player.Name, plr.Name, damage));
+ }
+ }
+
+ #endregion Time/PvpFun Commands
#region World Protection Commands
@@ -784,6 +1039,176 @@ namespace TShockAPI
Tools.Broadcast(string.Format("Spawn is now {0}.", (ConfigurationManager.SpawnProtect ? "protected" : "open")));
}
+ private static void Region(CommandArgs args)
+ {
+ string cmd = "help";
+ if (args.Parameters.Count > 0)
+ {
+ cmd = args.Parameters[0].ToLower();
+ }
+ switch (cmd)
+ {
+ case "set":
+ {
+ if (args.Parameters.Count == 2)
+ {
+ if (args.Parameters[1] == "1")
+ {
+ args.Player.TempArea.X = args.Player.TileX;
+ args.Player.TempArea.Y = args.Player.TileY;
+ args.Player.SendMessage("Set Temp Point 1", Color.Yellow);
+ }
+ else if (args.Parameters[1] == "2")
+ {
+ if (args.Player.TempArea.X != 0)
+ {
+ if (args.Player.TileX > args.Player.TempArea.X && args.Player.TileY > args.Player.TempArea.Y)
+ {
+ args.Player.TempArea.Width = args.Player.TileX - args.Player.TempArea.X;
+ args.Player.TempArea.Height = (args.Player.TileY + 3) - args.Player.TempArea.Y;
+ args.Player.SendMessage("Set Temp Point 2", Color.Yellow);
+ }
+ else
+ {
+ args.Player.SendMessage("Point 2 must be below and right of Point 1", Color.Yellow);
+ args.Player.SendMessage("Use /region clear to start again", Color.Yellow);
+ }
+ }
+ else
+ {
+ args.Player.SendMessage("You have not set Point 1 yet", Color.Red);
+ }
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /region set [1/2]", Color.Red);
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /region set [1/2]", Color.Red);
+ break;
+ }
+ case "define":
+ {
+ if (args.Parameters.Count > 1)
+ {
+ if (!args.Player.TempArea.IsEmpty)
+ {
+ string regionName = String.Join(" ", args.Parameters.GetRange(1, args.Parameters.Count - 1));
+ if (RegionManager.AddRegion(args.Player.TempArea.X, args.Player.TempArea.Y,
+ args.Player.TempArea.Width, args.Player.TempArea.Height,
+ regionName, Main.worldName))
+ {
+ args.Player.TempArea = Rectangle.Empty;
+ args.Player.SendMessage("Set region " + regionName, Color.Yellow);
+ }
+ else
+ {
+ args.Player.SendMessage("Region " + regionName + " already exists", Color.Red);
+ }
+ }
+ else
+ args.Player.SendMessage("Points not set up yet", Color.Red);
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /region define [name]", Color.Red);
+ break;
+ }
+ case "protect":
+ {
+ if (args.Parameters.Count == 3)
+ {
+ string regionName = args.Parameters[1];
+ if (args.Parameters[2].ToLower() == "true")
+ {
+ if (RegionManager.SetRegionState(regionName, true))
+ args.Player.SendMessage("Protected region " + regionName, Color.Yellow);
+ else
+ args.Player.SendMessage("Could not find specified region", Color.Red);
+ }
+ else if (args.Parameters[2].ToLower() == "false")
+ {
+ if (RegionManager.SetRegionState(regionName, false))
+ args.Player.SendMessage("Unprotected region " + regionName, Color.Yellow);
+ else
+ args.Player.SendMessage("Could not find specified region", Color.Red);
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /region protected [name] [true/false]", Color.Red);
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /region protected [name] [true/false]", Color.Red);
+ break;
+ }
+ case "delete":
+ {
+ if (args.Parameters.Count > 1)
+ {
+ string regionName = String.Join(" ", args.Parameters.GetRange(1, args.Parameters.Count - 1));
+ if (RegionManager.DeleteRegion(regionName))
+ args.Player.SendMessage("Deleted region " + regionName, Color.Yellow);
+ else
+ args.Player.SendMessage("Could not find specified region", Color.Red);
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /region delete [name]", Color.Red);
+ break;
+ }
+ case "clear":
+ {
+ args.Player.TempArea = Rectangle.Empty;
+ args.Player.SendMessage("Cleared temp area", Color.Yellow);
+ break;
+ }
+ case "allow":
+ {
+ if (args.Parameters.Count > 2)
+ {
+ string playerName = args.Parameters[1];
+ string regionName = "";
+ string playerIP = null;
+
+ for (int i = 2; i < args.Parameters.Count; i++)
+ {
+ if (regionName == "")
+ {
+ regionName = args.Parameters[2];
+ }
+ else
+ {
+ regionName = regionName + " " + args.Parameters[i];
+ }
+ }
+ if ((playerIP = Tools.GetPlayerIP(playerName)) != null)
+ {
+ if (RegionManager.AddNewUser(regionName, playerIP))
+ {
+ args.Player.SendMessage("Added user " + playerName + " to " + regionName, Color.Yellow);
+ RegionManager.WriteSettings();
+ }
+ else
+ args.Player.SendMessage("Region " + regionName + " not found", Color.Red);
+ }
+ else
+ {
+ args.Player.SendMessage("Player " + playerName + " not found", Color.Red);
+ }
+ }
+ else
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /region allow [name] [region]", Color.Red);
+ break;
+ }
+ case "help":
+ default:
+ {
+ args.Player.SendMessage("Avialable region commands:", Color.Green);
+ args.Player.SendMessage("/region set [1/2] /region define [name] /region protect [name] [true/false]", Color.Yellow);
+ args.Player.SendMessage("/region delete [name] /region clear (temporary region)", Color.Yellow);
+ args.Player.SendMessage("/region allow [name] [regionname]", Color.Yellow);
+ break;
+ }
+ }
+
+ }
+
#endregion World Protection Commands
#region General Commands
@@ -852,16 +1277,25 @@ namespace TShockAPI
private static void ThirdPerson(CommandArgs args)
{
- string msg = args.Message.Remove(0, 3);
- Tools.Broadcast(string.Format("*{0} {1}", args.Player.Name, msg), 205, 133, 63);
+ if (args.Parameters.Count == 0)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /me ", Color.Red);
+ return;
+ }
+ Tools.Broadcast(string.Format("*{0} {1}", args.Player.Name, String.Join(" ", args.Parameters)), 205, 133, 63);
}
private static void PartyChat(CommandArgs args)
{
+ if (args.Parameters.Count == 0)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /p ", Color.Red);
+ return;
+ }
int playerTeam = args.Player.Team;
if (playerTeam != 0)
{
- string msg = string.Format("<{0}> {1}", args.Player.Name, args.Message.Remove(0, 2));
+ string msg = string.Format("<{0}> {1}", args.Player.Name, String.Join(" ", args.Parameters));
foreach (TSPlayer player in TShock.Players)
{
if (player != null && player.Active && player.Team == playerTeam)
@@ -883,43 +1317,6 @@ namespace TShockAPI
#region Cheat Commands
- private static void Slap(CommandArgs args)
- {
- if (args.Parameters.Count < 1 || args.Parameters.Count > 2)
- {
- args.Player.SendMessage("Invalid syntax! Proper syntax: /slap [dmg]", Color.Red);
- return;
- }
- if (args.Parameters[0].Length == 0)
- {
- args.Player.SendMessage("Missing player name", Color.Red);
- return;
- }
-
- string plStr = args.Parameters[0];
- var player = Tools.FindPlayer(plStr);
- if (player.Count == 0)
- {
- args.Player.SendMessage("Invalid player!", Color.Red);
- }
- else if (player.Count > 1)
- {
- args.Player.SendMessage("More than one player matched!", Color.Red);
- }
- else
- {
- var plr = player[0];
- int damage = 5;
- if (args.Parameters.Count == 2)
- {
- int.TryParse(args.Parameters[1], out damage);
- }
- TShock.PlayerDamage(plr, damage);
- Tools.Broadcast(string.Format("{0} slapped {1} for {2} damage.",
- args.Player.Name, plr.Name, damage));
- }
- }
-
private static void Kill(CommandArgs args)
{
if (args.Parameters.Count < 1)
@@ -929,33 +1326,42 @@ namespace TShockAPI
}
string plStr = String.Join(" ", args.Parameters);
- var player = Tools.FindPlayer(plStr);
- if (player.Count == 0)
+ var players = Tools.FindPlayer(plStr);
+ if (players.Count == 0)
{
args.Player.SendMessage("Invalid player!", Color.Red);
}
- else if (player.Count > 1)
+ else if (players.Count > 1)
{
args.Player.SendMessage("More than one player matched!", Color.Red);
}
else
{
- var plr = player[0];
+ var plr = players[0];
+ plr.DamagePlayer(999999);
args.Player.SendMessage(string.Format("You just killed {0}!", plr.Name));
plr.SendMessage(string.Format("{0} just killed you!", args.Player.Name));
- TShock.PlayerDamage(plr, 999999);
}
}
private static void Butcher(CommandArgs args)
{
+ if (args.Parameters.Count > 1)
+ {
+ args.Player.SendMessage("Invalid syntax! Proper syntax: /butcher [killFriendly(true/false)]", Color.Red);
+ return;
+ }
+
+ bool killFriendly = true;
+ if (args.Parameters.Count == 1)
+ bool.TryParse(args.Parameters[0], out killFriendly);
+
int killcount = 0;
for (int i = 0; i < Main.npc.Length; i++)
{
- if (!Main.npc[i].townNPC && Main.npc[i].active)
+ if ( Main.npc[i].active && !Main.npc[i].townNPC && (!Main.npc[i].friendly || killFriendly))
{
- Main.npc[i].StrikeNPC(99999, 90f, 1);
- NetMessage.SendData(28, -1, -1, "", i, 99999, 90f, 1);
+ TSPlayer.Server.StrikeNPC(i, 99999, 90f, 1);
killcount++;
}
}
@@ -975,39 +1381,35 @@ namespace TShockAPI
return;
}
- int type = -1;
- if (!int.TryParse(args.Parameters[0], out type))
- type = TShock.GetItemID(String.Join(" ", args.Parameters));
-
- if (type < 1 || type >= Main.maxItemTypes)
+ var items = Tools.GetItemByIdOrName(String.Join(" ", args.Parameters));
+ if (items.Count == 0)
{
args.Player.SendMessage("Invalid item type!", Color.Red);
- return;
}
-
- if (!args.Player.RealPlayer)
+ else if (items.Count > 1)
{
- args.Player.SendMessage("You cant get items!");
- return;
+ args.Player.SendMessage(string.Format("More than one ({0}) item matched!", items.Count), Color.Red);
}
-
- bool flag = false;
- for (int i = 0; i < 40; i++)
+ else
{
- if (!args.TPlayer.inventory[i].active)
+ var item = items[0];
+ if (item.type >= 1 && item.type < Main.maxItemTypes)
{
- int id = Terraria.Item.NewItem(0, 0, 0, 0, type, 1, true);
- Main.item[id].position.X = args.Player.X;
- Main.item[id].position.Y = args.Player.Y;
- Main.item[id].stack = Main.item[id].maxStack;
- NetMessage.SendData(21, -1, -1, "", id, 0f, 0f, 0f);
- args.Player.SendMessage(string.Format("Got some {0}.", Main.item[id].name));
- flag = true;
- break;
+ if (args.Player.InventorySlotAvailable)
+ {
+ args.Player.GiveItem(item.type, item.name, item.width, item.height, item.maxStack);
+ args.Player.SendMessage(string.Format("Got some {0}.", item.name));
+ }
+ else
+ {
+ args.Player.SendMessage("You don't have free slots!", Color.Red);
+ }
+ }
+ else
+ {
+ args.Player.SendMessage("Invalid item type!", Color.Red);
}
}
- if (!flag)
- args.Player.SendMessage("You don't have free slots!", Color.Red);
}
private static void Give(CommandArgs args)
@@ -1028,101 +1430,102 @@ namespace TShockAPI
return;
}
- int type = -1;
- if (!int.TryParse(args.Parameters[0], out type))
- type = TShock.GetItemID(args.Parameters[0]);
+ var items = Tools.GetItemByIdOrName(args.Parameters[0]);
- if (type < 1 || type >= Main.maxItemTypes)
+ if (items.Count == 0)
{
args.Player.SendMessage("Invalid item type!", Color.Red);
- return;
}
-
- string plStr = args.Parameters[1];
- var player = Tools.FindPlayer(plStr);
- if (player.Count == 0)
+ else if (items.Count > 1)
{
- args.Player.SendMessage("Invalid player!", Color.Red);
- }
- else if (player.Count > 1)
- {
- args.Player.SendMessage("More than one player matched!", Color.Red);
+ args.Player.SendMessage(string.Format("More than one ({0}) item matched!", items.Count), Color.Red);
}
else
{
- var plr = player[0];
- bool flag = false;
- for (int i = 0; i < 40; i++)
+ var item = items[0];
+ if (item.type >= 1 && item.type < Main.maxItemTypes)
{
- if (!plr.TPlayer.inventory[i].active)
+ string plStr = args.Parameters[1];
+ var players = Tools.FindPlayer(plStr);
+ if (players.Count == 0)
{
- int id = Terraria.Item.NewItem(0, 0, 0, 0, type, 1, true);
- Main.item[id].position.X = plr.X;
- Main.item[id].position.Y = plr.Y;
- Main.item[id].stack = Main.item[id].maxStack;
- NetMessage.SendData(21, -1, -1, "", id, 0f, 0f, 0f);
- args.Player.SendMessage(string.Format("Gave {0} some {1}.", plr.Name, Main.item[id].name));
- plr.SendMessage(string.Format("{0} gave you some {1}.", args.Player.Name, Main.item[id].name));
- flag = true;
- break;
+ args.Player.SendMessage("Invalid player!", Color.Red);
+ }
+ else if (players.Count > 1)
+ {
+ args.Player.SendMessage("More than one player matched!", Color.Red);
+ }
+ else
+ {
+ var plr = players[0];
+ if (plr.InventorySlotAvailable)
+ {
+ plr.GiveItem(item.type, item.name, item.width, item.height, item.maxStack);
+ args.Player.SendMessage(string.Format("Gave {0} some {1}.", plr.Name, item.name));
+ plr.SendMessage(string.Format("{0} gave you some {1}.", args.Player.Name, item.name));
+ }
+ else
+ {
+ args.Player.SendMessage("Player does not have free slots!", Color.Red);
+ }
}
}
- if (!flag)
- args.Player.SendMessage("Player does not have free slots!", Color.Red);
+ else
+ {
+ args.Player.SendMessage("Invalid item type!", Color.Red);
+ }
}
}
private static void Heal(CommandArgs args)
{
+ TSPlayer playerToHeal;
if (args.Parameters.Count > 0)
{
string plStr = String.Join(" ", args.Parameters);
- var player = Tools.FindPlayer(plStr);
- if (player.Count == 0)
+ var players = Tools.FindPlayer(plStr);
+ if (players.Count == 0)
{
args.Player.SendMessage("Invalid player!", Color.Red);
+ return;
}
- else if (player.Count > 1)
+ else if (players.Count > 1)
{
args.Player.SendMessage("More than one player matched!", Color.Red);
+ return;
}
else
{
- var plr = player[0];
- DropHearts(plr.X, plr.Y, 20);
- if (plr == args.Player)
- {
- args.Player.SendMessage("You just got healed!");
- }
- else
- {
- args.Player.SendMessage(string.Format("You just healed {0}", plr.Name));
- plr.SendMessage(string.Format("{0} just healed you!", args.Player.Name));
- }
+ playerToHeal = players[0];
}
}
else if (!args.Player.RealPlayer)
{
args.Player.SendMessage("You cant heal yourself!");
+ return;
}
else
{
- DropHearts(args.Player.X, args.Player.Y, 20);
+ playerToHeal = args.Player;
+ }
+
+ Item heart = Tools.GetItemById(58);
+ Item star = Tools.GetItemById(184);
+ for (int i = 0; i < 20; i++)
+ playerToHeal.GiveItem(heart.type, heart.name, heart.width, heart.height, heart.maxStack);
+ for (int i = 0; i < 10; i++)
+ playerToHeal.GiveItem(star.type, star.name, star.width, star.height, star.maxStack);
+ if (playerToHeal == args.Player)
+ {
args.Player.SendMessage("You just got healed!");
}
- }
-
- private static void DropHearts(float x, float y, int count)
- {
- for (int i = 0; i < count; i++)
+ else
{
- int itemid = Terraria.Item.NewItem(1, 1, 1, 1, 58);
- Main.item[itemid].position.X = x;
- Main.item[itemid].position.Y = y;
- NetMessage.SendData(21, -1, -1, "", itemid, 0f, 0f, 0f);
+ args.Player.SendMessage(string.Format("You just healed {0}", playerToHeal.Name));
+ playerToHeal.SendMessage(string.Format("{0} just healed you!", args.Player.Name));
}
}
#endregion Cheat Comamnds
}
-}
\ No newline at end of file
+}
diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs
index f0a37a22..eff333b1 100644
--- a/TShockAPI/ConfigFile.cs
+++ b/TShockAPI/ConfigFile.cs
@@ -30,10 +30,11 @@ namespace TShockAPI
public bool BanCheaters = true;
public bool KickGriefers = true;
public bool BanGriefers = true;
- public bool BanKillTileAbusers;
- public bool KickKillTileAbusers;
+ public bool BanKillTileAbusers = true;
+ public bool KickKillTileAbusers = true;
public bool BanExplosives = true;
public bool KickExplosives = true;
+ public bool DisableExplosives = true;
public bool SpawnProtection = true;
public int SpawnProtectionRadius = 5;
public string DistributationAgent = "facepunch";
@@ -41,7 +42,22 @@ namespace TShockAPI
public bool RangeChecks = true;
public bool SpamChecks = false;
public bool DisableBuild = false;
+ public int TileThreshold = 20;
+
public float[] AdminChatRGB = {255, 0, 0};
public string AdminChatPrefix = "(Admin) ";
+
+ public int PvpThrottle = 0;
+
+ public int BackupInterval = 0;
+ public int BackupKeepFor = 60;
+
+ public bool RememberLeavePos = false;
+
+ public bool HardcoreOnly = false;
+ public bool KickOnHardcoreOnlyDeath = false;
+ public bool BanOnHardcoreOnlyDeath = false;
+
+ public bool AutoSave = true;
}
}
\ No newline at end of file
diff --git a/TShockAPI/ConfigurationManager.cs b/TShockAPI/ConfigurationManager.cs
index c826d134..fa89dc4b 100644
--- a/TShockAPI/ConfigurationManager.cs
+++ b/TShockAPI/ConfigurationManager.cs
@@ -44,6 +44,7 @@ namespace TShockAPI
public static bool KickTnt = true;
public static bool BanBoom = true;
public static bool KickBoom = true;
+ public static bool DisableBoom = true;
public static bool SpawnProtect = true;
public static bool RangeChecks = true;
public static int SpawnProtectRadius = 5;
@@ -54,6 +55,28 @@ namespace TShockAPI
public static bool DisableBuild = false;
public static float[] AdminChatRGB = {255, 0, 0};
public static string AdminChatPrefix = "(Admin) ";
+ public static bool RememberLeavePos = false;
+ public static int TileThreshold = 20;
+
+ ///
+ /// Don't allow pvp changing for x seconds.
+ ///
+ public static int PvpThrottle = 0;
+
+ ///
+ /// Backup every x minutes
+ ///
+ public static int BackupInterval = 0;
+ ///
+ /// Delete backups that are older than x mintues.
+ ///
+ public static int BackupKeepFor = 60;
+
+ public static bool HardcoreOnly = false;
+ public static bool KickOnHardcoreDeath = false;
+ public static bool BanOnHardcoreDeath = false;
+
+ public static bool AutoSave = true;
public static void ReadJsonConfiguration()
{
@@ -76,6 +99,7 @@ namespace TShockAPI
KickTnt = cfg.KickKillTileAbusers;
BanBoom = cfg.BanExplosives;
KickBoom = cfg.KickExplosives;
+ DisableBoom = cfg.DisableExplosives;
SpawnProtect = cfg.SpawnProtection;
SpawnProtectRadius = cfg.SpawnProtectionRadius;
DistributationAgent = cfg.DistributationAgent;
@@ -83,10 +107,19 @@ namespace TShockAPI
RangeChecks = cfg.RangeChecks;
SpamChecks = cfg.SpamChecks;
DisableBuild = cfg.DisableBuild;
+ TileThreshold = cfg.TileThreshold;
NPC.maxSpawns = DefaultMaxSpawns;
NPC.defaultSpawnRate = DefaultSpawnRate;
AdminChatRGB = cfg.AdminChatRGB;
AdminChatPrefix = cfg.AdminChatPrefix;
+ PvpThrottle = cfg.PvpThrottle;
+ BackupInterval = cfg.BackupInterval;
+ BackupKeepFor = cfg.BackupKeepFor;
+ RememberLeavePos = cfg.RememberLeavePos;
+ HardcoreOnly = cfg.HardcoreOnly;
+ KickOnHardcoreDeath = cfg.KickOnHardcoreOnlyDeath;
+ BanOnHardcoreDeath = cfg.BanOnHardcoreOnlyDeath;
+ AutoSave = cfg.AutoSave;
}
public static void WriteJsonConfiguration()
@@ -103,18 +136,28 @@ namespace TShockAPI
cfg.BanCheaters = BanCheater;
cfg.KickGriefers = KickGriefer;
cfg.BanGriefers = BanGriefer;
- cfg.BanKillTileAbusers = BanGriefer;
- cfg.KickKillTileAbusers = KickGriefer;
+ cfg.BanKillTileAbusers = BanTnt;
+ cfg.KickKillTileAbusers = KickTnt;
cfg.BanExplosives = BanBoom;
cfg.KickExplosives = KickBoom;
+ cfg.DisableExplosives = DisableBoom;
cfg.SpawnProtection = SpawnProtect;
cfg.SpawnProtectionRadius = SpawnProtectRadius;
cfg.MaxSlots = MaxSlots;
cfg.RangeChecks = RangeChecks;
cfg.SpamChecks = SpamChecks;
cfg.DisableBuild = DisableBuild;
+ cfg.TileThreshold = TileThreshold;
cfg.AdminChatRGB = AdminChatRGB;
cfg.AdminChatPrefix = AdminChatPrefix;
+ cfg.PvpThrottle = PvpThrottle;
+ cfg.BackupInterval = BackupInterval;
+ cfg.BackupKeepFor = BackupKeepFor;
+ cfg.RememberLeavePos = RememberLeavePos;
+ cfg.HardcoreOnly = HardcoreOnly;
+ cfg.BanOnHardcoreOnlyDeath = BanOnHardcoreDeath;
+ cfg.KickOnHardcoreOnlyDeath = KickOnHardcoreDeath;
+ cfg.AutoSave = AutoSave;
string json = JsonConvert.SerializeObject(cfg, Formatting.Indented);
TextWriter tr = new StreamWriter(FileTools.ConfigPath);
tr.Write(json);
diff --git a/TShockAPI/FileTools.cs b/TShockAPI/FileTools.cs
index a87f94af..d553af0c 100644
--- a/TShockAPI/FileTools.cs
+++ b/TShockAPI/FileTools.cs
@@ -29,7 +29,11 @@ namespace TShockAPI
public static readonly string WhitelistPath = Path.Combine(TShock.SavePath, "whitelist.txt");
public static readonly string GroupsPath = Path.Combine(TShock.SavePath, "groups.txt");
public static readonly string UsersPath = Path.Combine(TShock.SavePath, "users.txt");
+ public static readonly string ItemBansPath = Path.Combine(TShock.SavePath, "itembans.txt");
+ public static readonly string RememberedPosPath = Path.Combine(TShock.SavePath, "oldpos.xml");
public static readonly string ConfigPath = Path.Combine(TShock.SavePath, "config.json");
+ public static readonly string RegionsPath = Path.Combine(TShock.SavePath, "regions.xml");
+ public static readonly string WarpsPath = Path.Combine(TShock.SavePath, "warps.xml");
public static void CreateFile(string file)
{
@@ -60,6 +64,25 @@ namespace TShockAPI
CreateIfNot(WhitelistPath);
CreateIfNot(GroupsPath, Resources.groups);
CreateIfNot(UsersPath, Resources.users);
+ CreateIfNot(ItemBansPath, Resources.itembans);
+
+ //Copies if using old paths (Remove in future releases, after everyone is running this version +)
+ if (File.Exists("regions.xml") && !File.Exists(RegionsPath))
+ {
+ File.Move("regions.xml", RegionsPath);
+ }
+ else
+ {
+ CreateIfNot(RegionsPath);
+ }
+ if (File.Exists("warps.xml") && !File.Exists(WarpsPath))
+ {
+ File.Move("warps.xml", WarpsPath);
+ }
+ else
+ {
+ CreateIfNot(WarpsPath);
+ }
try
{
@@ -100,7 +123,23 @@ namespace TShockAPI
TextReader tr = new StreamReader(WhitelistPath);
string whitelist = tr.ReadToEnd();
ip = Tools.GetRealIP(ip);
- return whitelist.Contains(ip);
+ bool contains = whitelist.Contains(ip);
+ if (!contains)
+ {
+ var char2 = Environment.NewLine.ToCharArray();
+ var array = whitelist.Split(Environment.NewLine.ToCharArray());
+ foreach (var line in whitelist.Split(Environment.NewLine.ToCharArray()))
+ {
+ if (string.IsNullOrWhiteSpace(line))
+ continue;
+ contains = Tools.GetIPv4Address(line).Equals(ip);
+ if (contains)
+ return true;
+ }
+ return false;
+ }
+ else
+ return true;
}
}
}
\ No newline at end of file
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 9f43c8d1..ba7feda1 100755
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -1,426 +1,481 @@
-/*
-TShock, a server mod for Terraria
-Copyright (C) 2011 The TShock Team
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Text;
-using Microsoft.Xna.Framework;
-using StreamBinary;
-using Terraria;
-using TerrariaAPI;
-
-namespace TShockAPI
-{
- public delegate bool GetDataHandlerDelegate(GetDataHandlerArgs args);
- public class GetDataHandlerArgs : EventArgs
- {
- public TSPlayer Player { get; private set; }
- public MemoryStream Data { get; private set; }
-
- public Player TPlayer
- {
- get { return Player.TPlayer; }
- }
-
- public GetDataHandlerArgs(TSPlayer player, MemoryStream data)
- {
- Player = player;
- Data = data;
- }
- }
- public static class GetDataHandlers
- {
- private static Dictionary GetDataHandlerDelegates;
- private static bool[] BlacklistTiles;
-
- public static void InitGetDataHandler()
- {
- #region Blacklisted tiles
-
- BlacklistTiles = new bool[Main.maxTileSets];
- BlacklistTiles[0] = true;
- BlacklistTiles[1] = true;
- BlacklistTiles[2] = true;
- BlacklistTiles[6] = true;
- BlacklistTiles[7] = true;
- BlacklistTiles[8] = true;
- BlacklistTiles[9] = true;
- BlacklistTiles[22] = true;
- BlacklistTiles[23] = true;
- BlacklistTiles[25] = true;
- BlacklistTiles[30] = true;
- BlacklistTiles[37] = true;
- BlacklistTiles[38] = true;
- BlacklistTiles[39] = true;
- BlacklistTiles[40] = true;
- BlacklistTiles[41] = true;
- BlacklistTiles[43] = true;
- BlacklistTiles[44] = true;
- BlacklistTiles[45] = true;
- BlacklistTiles[46] = true;
- BlacklistTiles[47] = true;
- BlacklistTiles[53] = true;
- BlacklistTiles[54] = true;
- BlacklistTiles[56] = true;
- BlacklistTiles[57] = true;
- BlacklistTiles[58] = true;
- BlacklistTiles[59] = true;
- BlacklistTiles[60] = true;
- BlacklistTiles[63] = true;
- BlacklistTiles[64] = true;
- BlacklistTiles[65] = true;
- BlacklistTiles[66] = true;
- BlacklistTiles[67] = true;
- BlacklistTiles[68] = true;
- BlacklistTiles[70] = true;
- BlacklistTiles[75] = true;
- BlacklistTiles[76] = true;
-
- #endregion Blacklisted tiles
-
- GetDataHandlerDelegates = new Dictionary
- {
- {PacketTypes.PlayerInfo, HandlePlayerInfo},
- {PacketTypes.TileSendSection, HandleSendSection},
- {PacketTypes.PlayerUpdate, HandlePlayerUpdate},
- {PacketTypes.Tile, HandleTile},
- {PacketTypes.TileSendSquare, HandleSendTileSquare},
- {PacketTypes.NPCUpdate, HandleNpcUpdate},
- {PacketTypes.PlayerDamage, HandlePlayerDamage},
- {PacketTypes.ProjectileNew, HandleProjectileNew},
- {PacketTypes.TogglePVP, HandleTogglePvp},
- {PacketTypes.TileKill, HandleTileKill},
- {PacketTypes.PlayerKillMe, HandlePlayerKillMe},
- {PacketTypes.LiquidSet, HandleLiquidSet},
- };
- }
-
- public static bool HandlerGetData(PacketTypes type, TSPlayer player, MemoryStream data)
- {
- GetDataHandlerDelegate handler;
- if (GetDataHandlerDelegates.TryGetValue(type, out handler))
- {
- try
- {
- return handler(new GetDataHandlerArgs(player, data));
- }
- catch (Exception ex)
- {
- Log.Error(ex.ToString());
- }
- }
- return false;
- }
-
- private static bool HandlePlayerInfo(GetDataHandlerArgs args)
- {
- byte playerid = args.Data.ReadInt8();
- byte hair = args.Data.ReadInt8();
- Color hairColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
- Color skinColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
- Color eyeColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
- Color shirtColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
- Color underShirtColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
- Color pantsColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
- Color shoeColor = new Color(args.Data.ReadInt8(), args.Data.ReadInt8(), args.Data.ReadInt8());
- string name = Encoding.ASCII.GetString(args.Data.ReadBytes((int) (args.Data.Length - args.Data.Position - 1)));
-
- if (hair >= Main.maxHair)
- {
- Tools.ForceKick(args.Player, "Hair crash exploit.");
- return true;
- }
-
- if (name.Length > 32)
- {
- Tools.ForceKick(args.Player, "Name exceeded 32 characters.");
- return true;
- }
- if (name.Trim().Length == 0)
- {
- Tools.ForceKick(args.Player, "Empty Name.");
- return true;
- }
- var ban = TShock.Bans.GetBanByName(name);
- if (ban != null)
- {
- Tools.ForceKick(args.Player, string.Format("You are banned: {0}", ban.Reason));
- return true;
- }
- if (args.Player.ReceivedInfo)
- {
- return Tools.HandleGriefer(args.Player, "Sent client info more than once");
- }
-
- args.Player.ReceivedInfo = true;
- return false;
- }
-
- private static bool HandleSendTileSquare(GetDataHandlerArgs args)
- {
- short size = args.Data.ReadInt16();
- int x = args.Data.ReadInt32();
- int y = args.Data.ReadInt32();
- int plyX = Math.Abs(args.Player.TileX);
- int plyY = Math.Abs(args.Player.TileY);
- int tileX = Math.Abs(x);
- int tileY = Math.Abs(y);
- if (size > 5 || (ConfigurationManager.RangeChecks && (Math.Abs(plyX - tileX) > 32 || Math.Abs(plyY - tileY) > 32)))
- {
- Log.Debug(string.Format("SendTileSquare(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Size:{6})",
- plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), size));
- return Tools.HandleGriefer(args.Player, "Send Tile Square Abuse");
- }
- return false;
- }
-
- private static bool HandleTile(GetDataHandlerArgs args)
- {
- byte type = args.Data.ReadInt8();
- int x = args.Data.ReadInt32();
- int y = args.Data.ReadInt32();
- byte tiletype = args.Data.ReadInt8();
- if (type == 1 || type == 3)
- {
- int plyX = Math.Abs(args.Player.TileX);
- int plyY = Math.Abs(args.Player.TileY);
- int tileX = Math.Abs(x);
- int tileY = Math.Abs(y);
-
- if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32)))
- {
- Log.Debug(string.Format("TilePlaced(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Type:{6})",
- plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), tiletype));
- return Tools.HandleGriefer(args.Player, "Placing impossible to place blocks.");
- }
- }
- if (ConfigurationManager.DisableBuild)
- {
- if (!args.Player.Group.HasPermission("editspawn"))
- {
- args.Player.SendMessage("World protected from changes.", Color.Red);
- TShock.SendTileSquare(args.Player, x, y);
- return true;
- }
- }
- if (ConfigurationManager.SpawnProtect)
- {
- if (!args.Player.Group.HasPermission("editspawn"))
- {
- var flag = TShock.CheckSpawn(x, y);
- if (flag)
- {
- args.Player.SendMessage("Spawn protected from changes.", Color.Red);
- TShock.SendTileSquare(args.Player, x, y);
- return true;
- }
- }
- }
- if (type == 0 && BlacklistTiles[Main.tile[x, y].type] && args.Player.Active)
- {
- args.Player.TileThreshold++;
- var coords = new Vector2(x, y);
- if (!args.Player.TilesDestroyed.ContainsKey(coords))
- args.Player.TilesDestroyed.Add(coords, Main.tile[x, y]);
- }
-
- return false;
- }
-
- private static bool HandleTogglePvp(GetDataHandlerArgs args)
- {
- int id = args.Data.ReadByte();
- bool pvp = args.Data.ReadBoolean();
-
- args.TPlayer.hostile = pvp;
- if (id != args.Player.Index)
- args.TPlayer.hostile = true;
- if (ConfigurationManager.PermaPvp)
- args.TPlayer.hostile = true;
- NetMessage.SendData(30, -1, -1, "", args.Player.Index);
- return true;
- }
-
- private static bool HandleSendSection(GetDataHandlerArgs args)
- {
- return Tools.HandleGriefer(args.Player, "SendSection abuse.");
- }
-
- private static bool HandleNpcUpdate(GetDataHandlerArgs args)
- {
- return Tools.HandleGriefer(args.Player, "Spawn NPC abuse");
- }
-
- private static bool HandlePlayerUpdate(GetDataHandlerArgs args)
- {
- byte plr = args.Data.ReadInt8();
- byte control = args.Data.ReadInt8();
- byte item = args.Data.ReadInt8();
- float posx = args.Data.ReadSingle();
- float posy = args.Data.ReadSingle();
- float velx = args.Data.ReadSingle();
- float vely = args.Data.ReadSingle();
-
- if (Main.verboseNetplay)
- Debug.WriteLine("Update: {{{0},{1}}} {{{2}, {3}}}", (int)posx, (int)posy, (int)velx, (int)vely);
-
- if (plr != args.Player.Index)
- {
- return Tools.HandleGriefer(args.Player, "Update Player abuse");
- }
- return false;
- }
-
- private static bool HandleProjectileNew(GetDataHandlerArgs args)
- {
- short ident = args.Data.ReadInt16();
- float posx = args.Data.ReadSingle();
- float posy = args.Data.ReadSingle();
- float velx = args.Data.ReadSingle();
- float vely = args.Data.ReadSingle();
- float knockback = args.Data.ReadSingle();
- short dmg = args.Data.ReadInt16();
- byte owner = args.Data.ReadInt8();
- byte type = args.Data.ReadInt8();
-
- if (type == 29 || type == 28 || type == 37)
- {
- Log.Debug(string.Format("Explosive(PlyXY:{0}_{1}, Type:{2})", args.Player.TileX, args.Player.TileY, type));
- return Tools.HandleExplosivesUser(args.Player, "Throwing an explosive device.");
- }
- return false;
- }
-
- private static bool HandlePlayerKillMe(GetDataHandlerArgs args)
- {
- byte id = args.Data.ReadInt8();
- byte hitdirection = args.Data.ReadInt8();
- short dmg = args.Data.ReadInt16();
- bool pvp = args.Data.ReadBoolean();
-
- if (id != args.Player.Index)
- {
- return Tools.HandleGriefer(args.Player, "Trying to execute KillMe on someone else.");
- }
- return false;
- }
-
- private static bool HandlePlayerDamage(GetDataHandlerArgs args)
- {
- byte playerid = args.Data.ReadInt8();
- byte direction = args.Data.ReadInt8();
- Int16 damage = args.Data.ReadInt16();
- byte pvp = args.Data.ReadInt8();
-
- return !TShock.Players[playerid].TPlayer.hostile;
- }
-
- private static bool HandleLiquidSet(GetDataHandlerArgs args)
- {
- int x = args.Data.ReadInt32();
- int y = args.Data.ReadInt32();
- byte liquid = args.Data.ReadInt8();
- bool lava = args.Data.ReadBoolean();
-
- //The liquid was picked up.
- if (liquid == 0)
- return false;
-
- int plyX = Math.Abs(args.Player.TileX);
- int plyY = Math.Abs(args.Player.TileY);
- int tileX = Math.Abs(x);
- int tileY = Math.Abs(y);
-
- bool bucket = false;
- for (int i = 0; i < 44; i++)
- {
- if (args.TPlayer.inventory[i].type >= 205 && args.TPlayer.inventory[i].type <= 207)
- {
- bucket = true;
- break;
- }
- }
-
- if (lava && !args.Player.Group.HasPermission("canlava"))
- {
- args.Player.SendMessage("You do not have permission to use lava", Color.Red);
- Tools.SendLogs(string.Format("{0} tried using lava", args.Player.Name), Color.Red);
- // TODO need to revert player changes so they are insync with server
- return true;
- }
- if (!lava && !args.Player.Group.HasPermission("canwater"))
- {
- args.Player.SendMessage("You do not have permission to use water", Color.Red);
- Tools.SendLogs(string.Format("{0} tried using water", args.Player.Name), Color.Red);
- // TODO need to revert player changes so they are insync with server
- return true;
- }
-
- if (!bucket)
- {
- Log.Debug(string.Format("{0}(PlyXY:{1}_{2}, TileXY:{3}_{4}, Result:{5}_{6}, Amount:{7})",
- lava ? "Lava" : "Water", plyX, plyY, tileX, tileY,
- Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid));
- return Tools.HandleGriefer(args.Player, "Manipulating liquid without bucket."); ;
- }
- if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32)))
- {
- Log.Debug(string.Format("Liquid(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Amount:{6})",
- plyX, plyY,
- tileX, tileY,
- Math.Abs(plyX - tileX), Math.Abs(plyY - tileY),
- liquid
- ));
- return Tools.HandleGriefer(args.Player, "Placing impossible to place liquid."); ;
- }
-
- if (ConfigurationManager.SpawnProtect)
- {
- if (!args.Player.Group.HasPermission("editspawn"))
- {
- var flag = TShock.CheckSpawn(x, y);
- if (flag)
- {
- args.Player.SendMessage("The spawn is protected!", Color.Red);
- // TODO need to revert player changes so they are insync with server
- return true;
- }
- }
- }
- return false;
- }
-
- private static bool HandleTileKill(GetDataHandlerArgs args)
- {
- int tilex = args.Data.ReadInt32();
- int tiley = args.Data.ReadInt32();
- if (tilex < 0 || tilex >= Main.maxTilesX || tiley < 0 || tiley >= Main.maxTilesY)
- return false;
-
- if (Main.tile[tilex, tiley].type != 0x15) //Chest
- {
- Log.Debug(string.Format("TileKill(TileXY:{0}_{1}, Type:{2})",
- tilex, tiley, Main.tile[tilex, tiley].type));
- Tools.ForceKick(args.Player, string.Format("Tile Kill abuse ({0})", Main.tile[tilex, tiley].type));
- return true;
- }
- return false;
- }
- }
-}
+/*
+TShock, a server mod for Terraria
+Copyright (C) 2011 The TShock Team
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using Microsoft.Xna.Framework;
+using Terraria;
+using TerrariaAPI;
+using XNAHelpers;
+
+namespace TShockAPI
+{
+ public delegate bool GetDataHandlerDelegate(GetDataHandlerArgs args);
+ public class GetDataHandlerArgs : EventArgs
+ {
+ public TSPlayer Player { get; private set; }
+ public MemoryStream Data { get; private set; }
+
+ public Player TPlayer
+ {
+ get { return Player.TPlayer; }
+ }
+
+ public GetDataHandlerArgs(TSPlayer player, MemoryStream data)
+ {
+ Player = player;
+ Data = data;
+ }
+ }
+ public static class GetDataHandlers
+ {
+ private static Dictionary GetDataHandlerDelegates;
+ private static bool[] BlacklistTiles;
+
+ public static void InitGetDataHandler()
+ {
+ #region Blacklisted tiles
+
+ BlacklistTiles = new bool[Main.maxTileSets];
+ BlacklistTiles[0] = true;
+ BlacklistTiles[1] = true;
+ BlacklistTiles[2] = true;
+ BlacklistTiles[6] = true;
+ BlacklistTiles[7] = true;
+ BlacklistTiles[8] = true;
+ BlacklistTiles[9] = true;
+ BlacklistTiles[22] = true;
+ BlacklistTiles[23] = true;
+ BlacklistTiles[25] = true;
+ BlacklistTiles[30] = true;
+ BlacklistTiles[37] = true;
+ BlacklistTiles[38] = true;
+ BlacklistTiles[39] = true;
+ BlacklistTiles[40] = true;
+ BlacklistTiles[41] = true;
+ BlacklistTiles[43] = true;
+ BlacklistTiles[44] = true;
+ BlacklistTiles[45] = true;
+ BlacklistTiles[46] = true;
+ BlacklistTiles[47] = true;
+ BlacklistTiles[53] = true;
+ BlacklistTiles[54] = true;
+ BlacklistTiles[56] = true;
+ BlacklistTiles[57] = true;
+ BlacklistTiles[58] = true;
+ BlacklistTiles[59] = true;
+ BlacklistTiles[60] = true;
+ BlacklistTiles[63] = true;
+ BlacklistTiles[64] = true;
+ BlacklistTiles[65] = true;
+ BlacklistTiles[66] = true;
+ BlacklistTiles[67] = true;
+ BlacklistTiles[68] = true;
+ BlacklistTiles[70] = true;
+ BlacklistTiles[75] = true;
+ BlacklistTiles[76] = true;
+
+ #endregion Blacklisted tiles
+
+ GetDataHandlerDelegates = new Dictionary
+ {
+ {PacketTypes.PlayerInfo, HandlePlayerInfo},
+ {PacketTypes.TileSendSection, HandleSendSection},
+ {PacketTypes.PlayerUpdate, HandlePlayerUpdate},
+ {PacketTypes.Tile, HandleTile},
+ {PacketTypes.TileSendSquare, HandleSendTileSquare},
+ {PacketTypes.NPCUpdate, HandleNpcUpdate},
+ {PacketTypes.PlayerDamage, HandlePlayerDamage},
+ {PacketTypes.ProjectileNew, HandleProjectileNew},
+ {PacketTypes.TogglePVP, HandleTogglePvp},
+ {PacketTypes.TileKill, HandleTileKill},
+ {PacketTypes.PlayerKillMe, HandlePlayerKillMe},
+ {PacketTypes.LiquidSet, HandleLiquidSet},
+ {PacketTypes.PlayerSpawn, HandleSpawn},
+ };
+ }
+
+ public static bool HandlerGetData(PacketTypes type, TSPlayer player, MemoryStream data)
+ {
+ GetDataHandlerDelegate handler;
+ if (GetDataHandlerDelegates.TryGetValue(type, out handler))
+ {
+ try
+ {
+ return handler(new GetDataHandlerArgs(player, data));
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex.ToString());
+ }
+ }
+ return false;
+ }
+
+ private static bool HandlePlayerInfo(GetDataHandlerArgs args)
+ {
+ byte playerid = args.Data.ReadInt8();
+ byte hair = args.Data.ReadInt8();
+ //Various colours here
+
+ args.Data.Position += 21;
+ bool hardcore = args.Data.ReadBoolean();
+ string name = Encoding.ASCII.GetString(args.Data.ReadBytes((int)(args.Data.Length - args.Data.Position - 1)));
+
+ if (hair >= Main.maxHair)
+ {
+ Tools.ForceKick(args.Player, "Hair crash exploit.");
+ return true;
+ }
+ if (name.Length > 32)
+ {
+ Tools.ForceKick(args.Player, "Name exceeded 32 characters.");
+ return true;
+ }
+ if (name.Trim().Length == 0)
+ {
+ Tools.ForceKick(args.Player, "Empty Name.");
+ return true;
+ }
+ var ban = TShock.Bans.GetBanByName(name);
+ if (ban != null)
+ {
+ Tools.ForceKick(args.Player, string.Format("You are banned: {0}", ban.Reason));
+ return true;
+ }
+ if (args.Player.ReceivedInfo)
+ {
+ return Tools.HandleGriefer(args.Player, "Sent client info more than once");
+ }
+ if (ConfigurationManager.HardcoreOnly)
+ if (!hardcore)
+ {
+ Tools.ForceKick(args.Player, "Server is set to hardcore characters only!");
+ return true;
+ }
+
+ args.Player.ReceivedInfo = true;
+ return false;
+ }
+
+ private static bool HandleSendTileSquare(GetDataHandlerArgs args)
+ {
+ short size = args.Data.ReadInt16();
+ int x = args.Data.ReadInt32();
+ int y = args.Data.ReadInt32();
+ int plyX = Math.Abs(args.Player.TileX);
+ int plyY = Math.Abs(args.Player.TileY);
+ int tileX = Math.Abs(x);
+ int tileY = Math.Abs(y);
+ if (size > 5 || (ConfigurationManager.RangeChecks && (Math.Abs(plyX - tileX) > 32 || Math.Abs(plyY - tileY) > 32)))
+ {
+ Log.Debug(string.Format("SendTileSquare(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Size:{6})",
+ plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), size));
+ return Tools.HandleGriefer(args.Player, "Send Tile Square Abuse");
+ }
+ return false;
+ }
+
+ private static bool HandleTile(GetDataHandlerArgs args)
+ {
+ byte type = args.Data.ReadInt8();
+ int x = args.Data.ReadInt32();
+ int y = args.Data.ReadInt32();
+ byte tiletype = args.Data.ReadInt8();
+ if (type == 1 || type == 3)
+ {
+ int plyX = Math.Abs(args.Player.TileX);
+ int plyY = Math.Abs(args.Player.TileY);
+ int tileX = Math.Abs(x);
+ int tileY = Math.Abs(y);
+
+ if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32)))
+ {
+ if (!(type == 1 && ((tiletype == 0 && args.Player.TPlayer.selectedItem == 114) || (tiletype == 53 && args.Player.TPlayer.selectedItem == 266))))
+ {
+ Log.Debug(string.Format("TilePlaced(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Type:{6})",
+ plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), tiletype));
+ return Tools.HandleGriefer(args.Player, "Placing impossible to place blocks.");
+ }
+ }
+ if (tiletype == 48 && !args.Player.Group.HasPermission("canspike"))
+ {
+ args.Player.SendMessage("You do not have permission to place spikes.", Color.Red);
+ Tools.SendLogs(string.Format("{0} tried to place spikes", args.Player.Name), Color.Red);
+ args.Player.SendTileSquare(x, y);
+ return true;
+ }
+ }
+ if (!args.Player.Group.HasPermission("editspawn") && RegionManager.InProtectedArea(x, y, Tools.GetPlayerIP(args.Player.Name)))
+ {
+ args.Player.SendMessage("Region protected from changes.", Color.Red);
+ args.Player.SendTileSquare(x, y);
+ return true;
+ }
+ if (ConfigurationManager.DisableBuild)
+ {
+ if (!args.Player.Group.HasPermission("editspawn"))
+ {
+ args.Player.SendMessage("World protected from changes.", Color.Red);
+ args.Player.SendTileSquare(x, y);
+ return true;
+ }
+ }
+ if (ConfigurationManager.SpawnProtect)
+ {
+ if (!args.Player.Group.HasPermission("editspawn"))
+ {
+ var flag = TShock.CheckSpawn(x, y);
+ if (flag)
+ {
+ args.Player.SendMessage("Spawn protected from changes.", Color.Red);
+ args.Player.SendTileSquare(x, y);
+ return true;
+ }
+ }
+ }
+ if (type == 0 && BlacklistTiles[Main.tile[x, y].type] && args.Player.Active)
+ {
+ args.Player.TileThreshold++;
+ var coords = new Vector2(x, y);
+ if (!args.Player.TilesDestroyed.ContainsKey(coords))
+ args.Player.TilesDestroyed.Add(coords, Main.tile[x, y]);
+ }
+ if (args.Player.LastExplosive != null)
+ if ((DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds < 1000)
+ {
+ args.Player.SendMessage("Please wait another " + (1000 - (DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds).ToString() + " milliseconds before placing/destroying tiles", Color.Red);
+ args.Player.SendTileSquare(x, y);
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool HandleTogglePvp(GetDataHandlerArgs args)
+ {
+ int id = args.Data.ReadByte();
+ bool pvp = args.Data.ReadBoolean();
+
+ long seconds = (long)(DateTime.UtcNow - args.Player.LastPvpChange).TotalSeconds;
+ if (ConfigurationManager.PvpThrottle > 0 && seconds < ConfigurationManager.PvpThrottle)
+ {
+ args.Player.SendMessage(string.Format("You cannot change pvp status for {0} seconds", ConfigurationManager.PvpThrottle - seconds), 255, 0, 0);
+ args.Player.SetPvP(id != args.Player.Index || ConfigurationManager.PermaPvp ? true : args.TPlayer.hostile);
+ }
+ else
+ {
+ args.Player.SetPvP(id != args.Player.Index || ConfigurationManager.PermaPvp ? true : pvp);
+ }
+ return true;
+ }
+
+ private static bool HandleSendSection(GetDataHandlerArgs args)
+ {
+ return Tools.HandleGriefer(args.Player, "SendSection abuse.");
+ }
+
+ private static bool HandleNpcUpdate(GetDataHandlerArgs args)
+ {
+ return Tools.HandleGriefer(args.Player, "Spawn NPC abuse");
+ }
+
+ private static bool HandlePlayerUpdate(GetDataHandlerArgs args)
+ {
+ byte plr = args.Data.ReadInt8();
+ byte control = args.Data.ReadInt8();
+ byte item = args.Data.ReadInt8();
+ float posx = args.Data.ReadSingle();
+ float posy = args.Data.ReadSingle();
+ float velx = args.Data.ReadSingle();
+ float vely = args.Data.ReadSingle();
+
+ if (Main.verboseNetplay)
+ Debug.WriteLine("Update: {{{0},{1}}} {{{2}, {3}}}", (int)posx, (int)posy, (int)velx, (int)vely);
+
+ if (plr != args.Player.Index)
+ {
+ return Tools.HandleGriefer(args.Player, "Update Player abuse");
+ }
+
+ return false;
+ }
+
+ private static bool HandleProjectileNew(GetDataHandlerArgs args)
+ {
+ short ident = args.Data.ReadInt16();
+ float posx = args.Data.ReadSingle();
+ float posy = args.Data.ReadSingle();
+ float velx = args.Data.ReadSingle();
+ float vely = args.Data.ReadSingle();
+ float knockback = args.Data.ReadSingle();
+ short dmg = args.Data.ReadInt16();
+ byte owner = args.Data.ReadInt8();
+ byte type = args.Data.ReadInt8();
+
+ if (type == 29 || type == 28 || type == 37)
+ {
+ Log.Debug(string.Format("Explosive(PlyXY:{0}_{1}, Type:{2})", args.Player.TileX, args.Player.TileY, type));
+ if (ConfigurationManager.DisableBoom && (!args.Player.Group.HasPermission("useexplosives") || !args.Player.Group.HasPermission("ignoregriefdetection")))
+ {
+ Main.projectile[ident].type = 0;
+ args.Player.SendData(PacketTypes.ProjectileNew, "", ident);
+ args.Player.SendMessage("Explosives are disabled!", Color.Red);
+ args.Player.LastExplosive = DateTime.UtcNow;
+ //return true;
+ }
+ else
+ return Tools.HandleExplosivesUser(args.Player, "Throwing an explosive device.");
+ }
+ return false;
+ }
+
+ private static bool HandlePlayerKillMe(GetDataHandlerArgs args)
+ {
+ byte id = args.Data.ReadInt8();
+ if (id != args.Player.Index)
+ {
+ return Tools.HandleGriefer(args.Player, "Trying to execute KillMe on someone else.");
+ }
+ return false;
+ }
+
+ private static bool HandlePlayerDamage(GetDataHandlerArgs args)
+ {
+ byte playerid = args.Data.ReadInt8();
+ return !TShock.Players[playerid].TPlayer.hostile;
+ }
+
+ private static bool HandleLiquidSet(GetDataHandlerArgs args)
+ {
+ int x = args.Data.ReadInt32();
+ int y = args.Data.ReadInt32();
+ byte liquid = args.Data.ReadInt8();
+ bool lava = args.Data.ReadBoolean();
+
+ //The liquid was picked up.
+ if (liquid == 0)
+ return false;
+
+ int plyX = Math.Abs(args.Player.TileX);
+ int plyY = Math.Abs(args.Player.TileY);
+ int tileX = Math.Abs(x);
+ int tileY = Math.Abs(y);
+
+ bool bucket = false;
+ for (int i = 0; i < 44; i++)
+ {
+ if (args.TPlayer.inventory[i].type >= 205 && args.TPlayer.inventory[i].type <= 207)
+ {
+ bucket = true;
+ break;
+ }
+ }
+
+ if (lava && !args.Player.Group.HasPermission("canlava"))
+ {
+ args.Player.SendMessage("You do not have permission to use lava", Color.Red);
+ Tools.SendLogs(string.Format("{0} tried using lava", args.Player.Name), Color.Red);
+ args.Player.SendTileSquare(x, y);
+ return true;
+ }
+ if (!lava && !args.Player.Group.HasPermission("canwater"))
+ {
+ args.Player.SendMessage("You do not have permission to use water", Color.Red);
+ Tools.SendLogs(string.Format("{0} tried using water", args.Player.Name), Color.Red);
+ args.Player.SendTileSquare(x, y);
+ return true;
+ }
+
+ if (!bucket)
+ {
+ Log.Debug(string.Format("{0}(PlyXY:{1}_{2}, TileXY:{3}_{4}, Result:{5}_{6}, Amount:{7})",
+ lava ? "Lava" : "Water", plyX, plyY, tileX, tileY,
+ Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid));
+ return Tools.HandleGriefer(args.Player, "Manipulating liquid without bucket."); ;
+ }
+ if (ConfigurationManager.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32)))
+ {
+ Log.Debug(string.Format("Liquid(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Amount:{6})",
+ plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid));
+ return Tools.HandleGriefer(args.Player, "Placing impossible to place liquid."); ;
+ }
+
+ if (ConfigurationManager.SpawnProtect)
+ {
+ if (!args.Player.Group.HasPermission("editspawn"))
+ {
+ var flag = TShock.CheckSpawn(x, y);
+ if (flag)
+ {
+ args.Player.SendMessage("The spawn is protected!", Color.Red);
+ args.Player.SendTileSquare(x, y);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static bool HandleTileKill(GetDataHandlerArgs args)
+ {
+ int tilex = args.Data.ReadInt32();
+ int tiley = args.Data.ReadInt32();
+ if (tilex < 0 || tilex >= Main.maxTilesX || tiley < 0 || tiley >= Main.maxTilesY)
+ return false;
+
+ if (Main.tile[tilex, tiley].type != 0x15) //Chest
+ {
+ Log.Debug(string.Format("TileKill(TileXY:{0}_{1}, Type:{2})",
+ tilex, tiley, Main.tile[tilex, tiley].type));
+ Tools.ForceKick(args.Player, string.Format("Tile Kill abuse ({0})", Main.tile[tilex, tiley].type));
+ return true;
+ }
+ return false;
+ }
+
+ private static bool HandleSpawn(GetDataHandlerArgs args)
+ {
+ byte player = args.Data.ReadInt8();
+ int spawnx = args.Data.ReadInt32();
+ int spawny = args.Data.ReadInt32();
+
+ if (args.Player.InitSpawn)
+ {
+ if (ConfigurationManager.HardcoreOnly && (ConfigurationManager.KickOnHardcoreDeath || ConfigurationManager.BanOnHardcoreDeath))
+ if (args.TPlayer.selectedItem != 50)
+ {
+ if (ConfigurationManager.BanOnHardcoreDeath)
+ {
+ if (!Tools.Ban(args.Player, "Death results in a ban"))
+ Tools.ForceKick(args.Player, "Death results in a ban, but can't ban you");
+ }
+ else
+ Tools.ForceKick(args.Player, "Death results in a kick");
+ return true;
+ }
+ }
+ else
+ args.Player.InitSpawn = true;
+
+ return false;
+ }
+ }
+}
diff --git a/TShockAPI/ItemManager.cs b/TShockAPI/ItemManager.cs
new file mode 100644
index 00000000..e1c2b97c
--- /dev/null
+++ b/TShockAPI/ItemManager.cs
@@ -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 BannedItems = new List();
+
+ 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;
+ }
+ }
+}
diff --git a/TShockAPI/Log.cs b/TShockAPI/Log.cs
index a674f16b..cb89e1e2 100644
--- a/TShockAPI/Log.cs
+++ b/TShockAPI/Log.cs
@@ -53,24 +53,6 @@ namespace TShockAPI
_logWriter = new StreamWriter(filename, !clear);
}
- ///
- /// Internal method which writes a message directly to the log file.
- ///
- 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();
- }
-
///
/// Checks whether the log level contains the specified flag.
///
@@ -116,6 +98,16 @@ namespace TShockAPI
Write(message, LogLevel.Info);
}
+ ///
+ /// Writes an informative string to the log file. Also outputs to the console.
+ ///
+ /// The message to be written.
+ public static void ConsoleInfo(String message)
+ {
+ Console.WriteLine(message);
+ Write(message, LogLevel.Info);
+ }
+
///
/// Writes a debug string to the log file.
///
@@ -124,5 +116,31 @@ namespace TShockAPI
{
Write(message, LogLevel.Debug);
}
+
+ ///
+ /// Internal method which writes a message directly to the log file.
+ ///
+ 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();
+ }
}
}
\ No newline at end of file
diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs
index a220c10d..9bbabf72 100644
--- a/TShockAPI/Properties/AssemblyInfo.cs
+++ b/TShockAPI/Properties/AssemblyInfo.cs
@@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
+[assembly: AssemblyVersion("2.3.0.0627")]
+[assembly: AssemblyFileVersion("2.3.0.0627")]
\ No newline at end of file
diff --git a/TShockAPI/RegionManager.cs b/TShockAPI/RegionManager.cs
new file mode 100644
index 00000000..1a7ccf5e
--- /dev/null
+++ b/TShockAPI/RegionManager.cs
@@ -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 Regions = new List();
+
+ 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 RegionAllowedIPs = new List();
+
+ 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;
+ }
+ }
+}
diff --git a/TShockAPI/RememberPosManager.cs b/TShockAPI/RememberPosManager.cs
new file mode 100644
index 00000000..bcab39c8
--- /dev/null
+++ b/TShockAPI/RememberPosManager.cs
@@ -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 RemeberedPosistions = new List();
+
+ 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;
+ }
+ }
+}
diff --git a/TShockAPI/Resources.Designer.cs b/TShockAPI/Resources.Designer.cs
index 24f858b6..69d5beef 100644
--- a/TShockAPI/Resources.Designer.cs
+++ b/TShockAPI/Resources.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.225
+// Runtime Version:4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -71,9 +71,9 @@ namespace TShockAPI {
///#ALWAYS DECLARE A GROUP'S PARENT BEFORE YOU DECLARE THE GROUP
///
///#currently avaliable permissions:
- ///#kick ban ignorecheatdetection
- ///#maintenance cfg causeevents spawnboss tp
- ///#spawnmob che [rest of string was truncated]";.
+ ///#reservedslot - reserved slot for player
+ ///#canwater - allow players to use water
+ ///#canlav [rest of string was truncated]";.
///
internal static string groups {
get {
@@ -81,6 +81,16 @@ namespace TShockAPI {
}
}
+ ///
+ /// 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.
+ ///
+ internal static string itembans {
+ get {
+ return ResourceManager.GetString("itembans", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to #format
///#ip group
diff --git a/TShockAPI/Resources.resx b/TShockAPI/Resources.resx
index e260f5f5..21b8b3ab 100644
--- a/TShockAPI/Resources.resx
+++ b/TShockAPI/Resources.resx
@@ -1,21 +1,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
- ..\TShockAPI\bin\Release\TShockAPI.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
\ No newline at end of file
diff --git a/Update/Update.csproj b/Update/Update.csproj
deleted file mode 100644
index f37c3dee..00000000
--- a/Update/Update.csproj
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
- Debug
- x86
- 8.0.30703
- 2.0
- {AF322FAB-9A32-43AA-A01A-76B2A039F711}
- Exe
- Properties
- Update
- UpdateTShock
- v4.0
- Client
- 512
-
-
- x86
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- x86
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- Resources.resx
-
-
-
-
- ResXFileCodeGenerator
- Resources.Designer.cs
- Designer
-
-
-
-
-
-
-
-
-
\ No newline at end of file