Merge pull request #490 from NyxStudios/general-devel
Feature Freeze! Fixes will be applied here until 12:00AM on Friday. After that, new changes will be held to Tuesday.
This commit is contained in:
commit
49dec8c05c
65 changed files with 3514 additions and 1658 deletions
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = crlf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.cs]
|
||||
indent_style = tab
|
||||
trim_trailing_whitespace = true
|
||||
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
* text=auto
|
||||
*.cs text eol=crlf
|
||||
*.sln text eol=crlf
|
||||
*.csproj text eol=crlf
|
||||
*.vsmdi text eol=crlf
|
||||
9
.travis.yml
Normal file
9
.travis.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
language: c
|
||||
install:
|
||||
- sudo apt-get install mono-devel mono-gmcs nunit-console
|
||||
script:
|
||||
- xbuild ./TShockAPI/TShockAPI.csproj
|
||||
notifications:
|
||||
irc: irc.rizon.net#tshock
|
||||
hipchat:
|
||||
secure: hpRLWiHF2j6O2qJOVs++aqAmryN6G5kY0SF26/rKCpQ7klhMlDZIgI1V1dbkKqlculFtW1neS0EBJyV9lmcV5b26H+KhlZYGN0j7q1VcOTM3rvtU6wW0Ap22uRLl2RrnA4kEsgDAsNouPOkyLZ19hlHAISlsId6G4+Rfqg6k+zQ=
|
||||
36
CONTRIBUTING
Normal file
36
CONTRIBUTING
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
### Issue Guidelines
|
||||
Please follow these simple requirements before posting an issue:
|
||||
|
||||
1. TShock version number
|
||||
2. Any stack traces that may have happened when the issue occurred
|
||||
3. How to reproduce the issue
|
||||
|
||||
### Pull Request Dev Guidelines
|
||||
|
||||
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/).
|
||||
|
||||
----
|
||||
|
||||
### Dev Team Guidelines
|
||||
|
||||
These guidelines are to be followed by all developers with commit level access to this repository:
|
||||
|
||||
- Do not, for any reason, submit code to the master branch before it hits the development branch first. If the development branch is far ahead, and a new bug fix is going out, branch master, then merge with master and remove your branch.
|
||||
- If you are found to do this, you will be the person merging and rebasing your code to fit general-devel.
|
||||
- Prior to posting any version on the website, you must tick the version in AssemblyInfo.cs. This is the versioning formula:
|
||||
- Major.Minor.Revision.BuildDate (tick Revision if you're fixing prior to an actual planned release)
|
||||
- Do not release any development builds on the forums without consulting another developer first.
|
||||
- __Document code prior to marking it done in JIRA__
|
||||
- Move any un-tested code to the "Needs Validation" section on JIRA prior to marking it as done.
|
||||
- Do not push changes to any branch without a proper issue being assigned in JIRA. If a feature isn't planned for this release, __it shouldn't be in the repo about to be released__.
|
||||
- Submit all pull requests to the general-devel branch prior to the master branch, or you will be ignored.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# TShock
|
||||
# TShock [](https://travis-ci.org/NyxStudios/TShock)
|
||||
|
||||
TShock is a server modification for Terraria, written in C#, and based upon the [Terraria Server API](https://github.com/Deathmax/TerrariaAPI-Server). It uses JSON for configuration management, and offers several features not present in the Terraria Server normally.
|
||||
|
||||
|
|
@ -24,4 +24,3 @@ Feeling like helping out? Want to find an awesome server? Some awesome plugins?
|
|||
|
||||
* [Github Releases](https://github.com/TShock/TShock/releases)
|
||||
* [Download Archive](https://github.com/TShock/TShock/downloads)
|
||||
* [Latest Version (4.0.5)](https://s3.amazonaws.com/tshock/TShock+4.0.5.zip)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,12 +15,15 @@ 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.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Rests;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
|
|
@ -129,7 +132,7 @@ namespace TShockAPI
|
|||
|
||||
[Description("This will announce a player's location on join")] public bool EnableGeoIP;
|
||||
|
||||
[Description("This will turn on a token requirement for the /status API endpoint.")] public bool
|
||||
[Description("This will turn on token requirement for the public REST API endpoints.")] public bool
|
||||
EnableTokenEndpointAuthentication;
|
||||
|
||||
[Description("Deprecated. Use ServerName instead.")] public string ServerNickname = "TShock Server";
|
||||
|
|
@ -158,8 +161,6 @@ namespace TShockAPI
|
|||
|
||||
[Description("Time, in milliseconds, to disallow discarding items after logging in when ServerSideInventory is ON.")] public int LogonDiscardThreshold=250;
|
||||
|
||||
[Description("Disables reporting of playercount to the stat system.")] public bool DisablePlayerCountReporting;
|
||||
|
||||
[Description("Disables clown bomb projectiles from spawning.")] public bool DisableClownBombs;
|
||||
|
||||
[Description("Disables snow ball projectiles from spawning.")] public bool DisableSnowBalls;
|
||||
|
|
@ -236,15 +237,37 @@ namespace TShockAPI
|
|||
[Description("Prevent banks on SSI.")] public bool DisablePiggybanksOnSSI = false;
|
||||
|
||||
[Description("Prevent players from interacting with the world if dead.")] public bool PreventDeadModification =
|
||||
false;
|
||||
true;
|
||||
|
||||
[Description("Displays chat messages above players' heads, but will disable chat prefixes to compensate.")] public
|
||||
bool EnableChatAboveHeads = false;
|
||||
|
||||
[Description("Hide stat tracker console messages.")] public bool HideStatTrackerDebugMessages = true;
|
||||
|
||||
[Description("Force Christmas only events to occur all year.")] public bool ForceXmas = false;
|
||||
|
||||
[Description("Allows groups on the banned item allowed list to spawn banned items.")] public bool AllowAllowedGroupsToSpawnBannedItems = false;
|
||||
|
||||
[Description("Allows stacks in chests to be beyond the stack limit")] public bool IgnoreChestStacksOnLoad = false;
|
||||
|
||||
[Description("The path of the directory where logs should be written into.")] public string LogPath = "tshock";
|
||||
|
||||
[Description("Prevents players from placing tiles with an invalid style.")] public bool PreventInvalidPlaceStyle = true;
|
||||
|
||||
[Description("#.#.#. = Red/Blue/Green - RGB Colors for broadcasts. Max value: 255.")] public float[] BroadcastRGB =
|
||||
{127,255,212};
|
||||
|
||||
// TODO: Get rid of this when the old REST permission model is removed.
|
||||
[Description(
|
||||
"Whether the REST API should use the new permission model. Note: The old permission model will become depracted in the future."
|
||||
)] public bool RestUseNewPermissionModel = true;
|
||||
|
||||
[Description("A dictionary of REST tokens that external applications may use to make queries to your server.")]
|
||||
public Dictionary<string, SecureRest.TokenData> ApplicationRestTokens = new Dictionary<string, SecureRest.TokenData>();
|
||||
|
||||
[Description("The maximum value that a character may have for health.")] public int MaxHealth = 400;
|
||||
|
||||
[Description("The maximum value that a character may have for health.")] public int MaxMana = 400;
|
||||
|
||||
[Description("The number of reserved slots past your max server slot that can be joined by reserved players")] public int ReservedSlots = 20;
|
||||
/// <summary>
|
||||
/// Reads a configuration file from a given path
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,10 +15,10 @@ 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.Data;
|
||||
using System.IO;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
|
|
@ -34,7 +34,10 @@ namespace TShockAPI.DB
|
|||
var table = new SqlTable("Bans",
|
||||
new SqlColumn("IP", MySqlDbType.String, 16) {Primary = true},
|
||||
new SqlColumn("Name", MySqlDbType.Text),
|
||||
new SqlColumn("Reason", MySqlDbType.Text)
|
||||
new SqlColumn("Reason", MySqlDbType.Text),
|
||||
new SqlColumn("BanningUser", MySqlDbType.Text),
|
||||
new SqlColumn("Date", MySqlDbType.Text),
|
||||
new SqlColumn("Expiration", MySqlDbType.Text)
|
||||
);
|
||||
var creator = new SqlTableCreator(db,
|
||||
db.GetSqlType() == SqlType.Sqlite
|
||||
|
|
@ -58,7 +61,7 @@ namespace TShockAPI.DB
|
|||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE IP=@0", ip))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"));
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -77,7 +80,7 @@ namespace TShockAPI.DB
|
|||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
banlist.Add(new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason")));
|
||||
banlist.Add(new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration")));
|
||||
}
|
||||
return banlist;
|
||||
}
|
||||
|
|
@ -100,7 +103,7 @@ namespace TShockAPI.DB
|
|||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE " + namecol + "=@0", name))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"));
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -114,14 +117,14 @@ namespace TShockAPI.DB
|
|||
[Obsolete("This method is for signature compatibility for external code only")]
|
||||
public bool AddBan(string ip, string name, string reason)
|
||||
{
|
||||
return AddBan(ip, name, reason, false);
|
||||
return AddBan(ip, name, reason, false, "", "");
|
||||
}
|
||||
#endif
|
||||
public bool AddBan(string ip, string name = "", string reason = "", bool exceptions = false)
|
||||
public bool AddBan(string ip, string name = "", string reason = "", bool exceptions = false, string banner = "", string expiration = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
return database.Query("INSERT INTO Bans (IP, Name, Reason) VALUES (@0, @1, @2);", ip, name, reason) != 0;
|
||||
return database.Query("INSERT INTO Bans (IP, Name, Reason, BanningUser, Date, Expiration) VALUES (@0, @1, @2, @3, @4, @5);", ip, name, reason, banner, DateTime.Now.ToString("G"), expiration) != 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -180,11 +183,20 @@ namespace TShockAPI.DB
|
|||
|
||||
public string Reason { get; set; }
|
||||
|
||||
public Ban(string ip, string name, string reason)
|
||||
public string BanningUser { get; set; }
|
||||
|
||||
public string Date { get; set; }
|
||||
|
||||
public string Expiration { get; set; }
|
||||
|
||||
public Ban(string ip, string name, string reason, string banner, string date, string exp)
|
||||
{
|
||||
IP = ip;
|
||||
Name = name;
|
||||
Reason = reason;
|
||||
BanningUser = banner;
|
||||
Date = date;
|
||||
Expiration = exp;
|
||||
}
|
||||
|
||||
public Ban()
|
||||
|
|
@ -192,6 +204,9 @@ namespace TShockAPI.DB
|
|||
IP = string.Empty;
|
||||
Name = string.Empty;
|
||||
Reason = string.Empty;
|
||||
BanningUser = "";
|
||||
Date = "";
|
||||
Expiration = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,11 +15,12 @@ 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
|
|
@ -52,13 +53,29 @@ namespace TShockAPI.DB
|
|||
LoadPermisions();
|
||||
|
||||
// Add default groups if they don't exist
|
||||
AddDefaultGroup("guest", "", "canbuild,canregister,canlogin,canpartychat,cantalkinthird");
|
||||
AddDefaultGroup("default", "guest", "warp,canchangepassword");
|
||||
AddDefaultGroup("newadmin", "default", "kick,editspawn,reservedslot");
|
||||
AddDefaultGroup(TShock.Config.DefaultGuestGroupName, "",
|
||||
string.Join(",", Permissions.canbuild, Permissions.canregister, Permissions.canlogin, Permissions.canpartychat,
|
||||
Permissions.cantalkinthird));
|
||||
|
||||
AddDefaultGroup("default", TShock.Config.DefaultGuestGroupName,
|
||||
string.Join(",", Permissions.warp, Permissions.canchangepassword));
|
||||
|
||||
AddDefaultGroup("newadmin", "default",
|
||||
string.Join(",", Permissions.kick, Permissions.editspawn, Permissions.reservedslot));
|
||||
|
||||
AddDefaultGroup("admin", "newadmin",
|
||||
"ban,unban,whitelist,causeevents,spawnboss,spawnmob,managewarp,time,tp,pvpfun,kill,logs,immunetokick,tphere");
|
||||
AddDefaultGroup("trustedadmin", "admin", "maintenance,cfg,butcher,item,heal,immunetoban,usebanneditem,manageusers");
|
||||
AddDefaultGroup("vip", "default", "reservedslot");
|
||||
string.Join(",", Permissions.ban, Permissions.whitelist, Permissions.causeevents, Permissions.spawnboss,
|
||||
Permissions.spawnmob, Permissions.managewarp, Permissions.time, Permissions.tp, Permissions.slap,
|
||||
Permissions.kill, Permissions.logs,
|
||||
Permissions.immunetokick, Permissions.tphere));
|
||||
|
||||
AddDefaultGroup("trustedadmin", "admin",
|
||||
string.Join(",", Permissions.maintenance, "tshock.cfg.*", "tshock.world.*", Permissions.butcher, Permissions.item,
|
||||
Permissions.heal, Permissions.immunetoban, Permissions.usebanneditem));
|
||||
|
||||
AddDefaultGroup("vip", "default", string.Join(",", Permissions.reservedslot));
|
||||
|
||||
Group.DefaultGroup = GetGroupByName(TShock.Config.DefaultGuestGroupName);
|
||||
}
|
||||
|
||||
private void AddDefaultGroup(string name, string parent, string permissions)
|
||||
|
|
@ -114,7 +131,7 @@ namespace TShockAPI.DB
|
|||
if (!string.IsNullOrWhiteSpace(parentname))
|
||||
{
|
||||
var parent = groups.FirstOrDefault(gp => gp.Name == parentname);
|
||||
if (parent == null)
|
||||
if (parent == null || name == parentname)
|
||||
{
|
||||
var error = "Invalid parent {0} for group {1}".SFormat(parentname, group.Name);
|
||||
if (exceptions)
|
||||
|
|
@ -166,27 +183,40 @@ namespace TShockAPI.DB
|
|||
/// <param name="chatcolor">chatcolor</param>
|
||||
public void UpdateGroup(string name, string parentname, string permissions, string chatcolor)
|
||||
{
|
||||
if (!GroupExists(name))
|
||||
Group group = GetGroupByName(name);
|
||||
if (group == null)
|
||||
throw new GroupNotExistException(name);
|
||||
|
||||
Group parent = null;
|
||||
if (!string.IsNullOrWhiteSpace(parentname))
|
||||
{
|
||||
parent = groups.FirstOrDefault(gp => gp.Name == parentname);
|
||||
if (null == parent)
|
||||
throw new GroupManagerException("Invalid parent {0} for group {1}".SFormat(parentname, name));
|
||||
parent = GetGroupByName(parentname);
|
||||
if (parent == null || parent == group)
|
||||
throw new GroupManagerException("Invalid parent \"{0}\" for group \"{1}\".".SFormat(parentname, name));
|
||||
|
||||
// Check if the new parent would cause loops.
|
||||
List<Group> groupChain = new List<Group> { group, parent };
|
||||
Group checkingGroup = parent.Parent;
|
||||
while (checkingGroup != null)
|
||||
{
|
||||
if (groupChain.Contains(checkingGroup))
|
||||
throw new GroupManagerException(
|
||||
string.Format("Invalid parent \"{0}\" for group \"{1}\" would cause loops in the parent chain.", parentname, name));
|
||||
|
||||
groupChain.Add(checkingGroup);
|
||||
checkingGroup = checkingGroup.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: we use newgroup.XYZ to ensure any validation is also persisted to the DB
|
||||
var newgroup = new Group(name, parent, chatcolor, permissions);
|
||||
// Ensure any group validation is also persisted to the DB.
|
||||
var newGroup = new Group(name, parent, chatcolor, permissions);
|
||||
string query = "UPDATE GroupList SET Parent=@0, Commands=@1, ChatColor=@2 WHERE GroupName=@3";
|
||||
if (database.Query(query, parentname, newgroup.Permissions, string.Format("{0},{1},{2}", newgroup.R, newgroup.G, newgroup.B), name) != 1)
|
||||
throw new GroupManagerException("Failed to update group '" + name + "'");
|
||||
if (database.Query(query, parentname, newGroup.Permissions, string.Format("{0},{1},{2}", newGroup.R, newGroup.G, newGroup.B), name) != 1)
|
||||
throw new GroupManagerException(string.Format("Failed to update group \"{0}\".", name));
|
||||
|
||||
Group group = TShock.Utils.GetGroup(name);
|
||||
group.ChatColor = chatcolor;
|
||||
group.Permissions = permissions;
|
||||
group.Parent = TShock.Utils.GetGroup(parentname);
|
||||
group.Parent = parent;
|
||||
}
|
||||
|
||||
#if COMPAT_SIGS
|
||||
|
|
@ -252,53 +282,106 @@ namespace TShockAPI.DB
|
|||
|
||||
public void LoadPermisions()
|
||||
{
|
||||
// Create a temporary list so if there is an error it doesn't override the currently loaded groups with broken groups.
|
||||
var tempgroups = new List<Group>();
|
||||
tempgroups.Add(new SuperAdminGroup());
|
||||
|
||||
if (groups == null || groups.Count < 2)
|
||||
{
|
||||
groups.Clear();
|
||||
groups.AddRange(tempgroups);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var groupsparents = new List<Tuple<Group, string>>();
|
||||
List<Group> newGroups = new List<Group>(groups.Count);
|
||||
Dictionary<string,string> newGroupParents = new Dictionary<string, string>(groups.Count);
|
||||
using (var reader = database.QueryReader("SELECT * FROM GroupList"))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
var group = new Group(reader.Get<String>("GroupName"), null, reader.Get<String>("ChatColor"), reader.Get<String>("Commands"));
|
||||
group.Prefix = reader.Get<String>("Prefix");
|
||||
group.Suffix = reader.Get<String>("Suffix");
|
||||
groupsparents.Add(Tuple.Create(group, reader.Get<string>("Parent")));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var t in groupsparents)
|
||||
{
|
||||
var group = t.Item1;
|
||||
var parentname = t.Item2;
|
||||
if (!string.IsNullOrWhiteSpace(parentname))
|
||||
{
|
||||
var parent = groupsparents.FirstOrDefault(gp => gp.Item1.Name == parentname);
|
||||
if (parent == null)
|
||||
string groupName = reader.Get<string>("GroupName");
|
||||
if (groupName == "superadmin")
|
||||
{
|
||||
Log.ConsoleError("Invalid parent {0} for group {1}".SFormat(parentname, group.Name));
|
||||
Log.ConsoleInfo("WARNING: Group \"superadmin\" is defined in the database even though it's a reserved group name.");
|
||||
continue;
|
||||
}
|
||||
|
||||
newGroups.Add(new Group(groupName, null, reader.Get<string>("ChatColor"), reader.Get<string>("Commands")) {
|
||||
Prefix = reader.Get<string>("Prefix"),
|
||||
Suffix = reader.Get<string>("Suffix"),
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
newGroupParents.Add(groupName, reader.Get<string>("Parent"));
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Just in case somebody messed with the unique primary key.
|
||||
Log.ConsoleError("ERROR: Group name \"{0}\" occurs more than once. Keeping current group settings.");
|
||||
return;
|
||||
}
|
||||
group.Parent = parent.Item1;
|
||||
}
|
||||
tempgroups.Add(group);
|
||||
}
|
||||
|
||||
groups.Clear();
|
||||
groups.AddRange(tempgroups);
|
||||
try
|
||||
{
|
||||
// Get rid of deleted groups.
|
||||
for (int i = 0; i < groups.Count; i++)
|
||||
if (newGroups.All(g => g.Name != groups[i].Name))
|
||||
groups.RemoveAt(i--);
|
||||
|
||||
// Apply changed group settings while keeping the current instances and add new groups.
|
||||
foreach (Group newGroup in newGroups)
|
||||
{
|
||||
Group currentGroup = groups.FirstOrDefault(g => g.Name == newGroup.Name);
|
||||
if (currentGroup != null)
|
||||
newGroup.AssignTo(currentGroup);
|
||||
else
|
||||
groups.Add(newGroup);
|
||||
}
|
||||
|
||||
// Resolve parent groups.
|
||||
Debug.Assert(newGroups.Count == newGroupParents.Count);
|
||||
for (int i = 0; i < groups.Count; i++)
|
||||
{
|
||||
Group group = groups[i];
|
||||
string parentGroupName;
|
||||
if (!newGroupParents.TryGetValue(group.Name, out parentGroupName) || string.IsNullOrEmpty(parentGroupName))
|
||||
continue;
|
||||
|
||||
group.Parent = groups.FirstOrDefault(g => g.Name == parentGroupName);
|
||||
if (group.Parent == null)
|
||||
{
|
||||
Log.ConsoleError(
|
||||
"ERROR: Group \"{0}\" is referencing non existent parent group \"{1}\", parent reference was removed.",
|
||||
group.Name, parentGroupName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (group.Parent == group)
|
||||
Log.ConsoleInfo(
|
||||
"WARNING: Group \"{0}\" is referencing itself as parent group, parent reference was removed.", group.Name);
|
||||
|
||||
List<Group> groupChain = new List<Group> { group };
|
||||
Group checkingGroup = group;
|
||||
while (checkingGroup.Parent != null)
|
||||
{
|
||||
if (groupChain.Contains(checkingGroup.Parent))
|
||||
{
|
||||
Log.ConsoleError(
|
||||
"ERROR: Group \"{0}\" is referencing parent group \"{1}\" which is already part of the parent chain. Parent reference removed.",
|
||||
checkingGroup.Name, checkingGroup.Parent.Name);
|
||||
|
||||
checkingGroup.Parent = null;
|
||||
break;
|
||||
}
|
||||
groupChain.Add(checkingGroup);
|
||||
checkingGroup = checkingGroup.Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!groups.Any(g => g is SuperAdminGroup))
|
||||
groups.Add(new SuperAdminGroup());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
Log.ConsoleError("Error on reloading groups: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Linq;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Data;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,10 +15,10 @@ 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.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,13 +15,11 @@ 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.Data;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Terraria;
|
||||
|
||||
|
|
@ -238,25 +236,21 @@ namespace TShockAPI.DB
|
|||
return false;
|
||||
}
|
||||
Region top = null;
|
||||
for (int i = 0; i < Regions.Count; i++)
|
||||
{
|
||||
if (Regions[i].InArea(x,y) )
|
||||
{
|
||||
if (top == null)
|
||||
top = Regions[i];
|
||||
else
|
||||
{
|
||||
if (Regions[i].Z > top.Z)
|
||||
top = Regions[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Region region in Regions.ToList())
|
||||
{
|
||||
if (region.InArea(x, y))
|
||||
{
|
||||
if (top == null || region.Z > top.Z)
|
||||
top = region;
|
||||
}
|
||||
}
|
||||
return top == null || top.HasPermissionToBuildInRegion(ply);
|
||||
}
|
||||
|
||||
public bool InArea(int x, int y)
|
||||
{
|
||||
foreach (Region region in Regions)
|
||||
foreach (Region region in Regions.ToList())
|
||||
{
|
||||
if (x >= region.Area.Left && x <= region.Area.Right &&
|
||||
y >= region.Area.Top && y <= region.Area.Bottom &&
|
||||
|
|
@ -271,7 +265,7 @@ namespace TShockAPI.DB
|
|||
public List<string> InAreaRegionName(int x, int y)
|
||||
{
|
||||
List<string> regions = new List<string>() { };
|
||||
foreach (Region region in Regions)
|
||||
foreach (Region region in Regions.ToList())
|
||||
{
|
||||
if (x >= region.Area.Left && x <= region.Area.Right &&
|
||||
y >= region.Area.Top && y <= region.Area.Bottom &&
|
||||
|
|
@ -286,7 +280,7 @@ namespace TShockAPI.DB
|
|||
public List<Region> InAreaRegion(int x, int y)
|
||||
{
|
||||
List<Region> regions = new List<Region>() { };
|
||||
foreach (Region region in Regions)
|
||||
foreach (Region region in Regions.ToList())
|
||||
{
|
||||
if (x >= region.Area.Left && x <= region.Area.Right &&
|
||||
y >= region.Area.Top && y <= region.Area.Bottom &&
|
||||
|
|
@ -385,30 +379,36 @@ namespace TShockAPI.DB
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool AddNewUser(string regionName, String userName)
|
||||
public bool AddNewUser(string regionName, string userName)
|
||||
{
|
||||
try
|
||||
{
|
||||
string MergedIDs = string.Empty;
|
||||
string mergedIDs = string.Empty;
|
||||
using (
|
||||
var reader = database.QueryReader("SELECT * FROM Regions WHERE RegionName=@0 AND WorldID=@1", regionName,
|
||||
var reader = database.QueryReader("SELECT UserIds FROM Regions WHERE RegionName=@0 AND WorldID=@1", regionName,
|
||||
Main.worldID.ToString()))
|
||||
{
|
||||
if (reader.Read())
|
||||
MergedIDs = reader.Get<string>("UserIds");
|
||||
mergedIDs = reader.Get<string>("UserIds");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(MergedIDs))
|
||||
MergedIDs = Convert.ToString(TShock.Users.GetUserID(userName));
|
||||
else
|
||||
MergedIDs = MergedIDs + "," + Convert.ToString(TShock.Users.GetUserID(userName));
|
||||
string userIdToAdd = Convert.ToString(TShock.Users.GetUserID(userName));
|
||||
string[] ids = mergedIDs.Split(',');
|
||||
// Is the user already allowed to the region?
|
||||
if (ids.Contains(userIdToAdd))
|
||||
return true;
|
||||
|
||||
int q = database.Query("UPDATE Regions SET UserIds=@0 WHERE RegionName=@1 AND WorldID=@2", MergedIDs,
|
||||
if (string.IsNullOrEmpty(mergedIDs))
|
||||
mergedIDs = userIdToAdd;
|
||||
else
|
||||
mergedIDs = string.Concat(mergedIDs, ",", userIdToAdd);
|
||||
|
||||
int q = database.Query("UPDATE Regions SET UserIds=@0 WHERE RegionName=@1 AND WorldID=@2", mergedIDs,
|
||||
regionName, Main.worldID.ToString());
|
||||
foreach (var r in Regions)
|
||||
{
|
||||
if (r.Name == regionName && r.WorldID == Main.worldID.ToString())
|
||||
r.setAllowedIDs(MergedIDs);
|
||||
r.setAllowedIDs(mergedIDs);
|
||||
}
|
||||
return q != 0;
|
||||
}
|
||||
|
|
@ -471,27 +471,33 @@ namespace TShockAPI.DB
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool AllowGroup(string regionName, string groups)
|
||||
public bool AllowGroup(string regionName, string groupName)
|
||||
{
|
||||
string groupsNew = "";
|
||||
string mergedGroups = "";
|
||||
using (
|
||||
var reader = database.QueryReader("SELECT * FROM Regions WHERE RegionName=@0 AND WorldID=@1", regionName,
|
||||
var reader = database.QueryReader("SELECT Groups FROM Regions WHERE RegionName=@0 AND WorldID=@1", regionName,
|
||||
Main.worldID.ToString()))
|
||||
{
|
||||
if (reader.Read())
|
||||
groupsNew = reader.Get<string>("Groups");
|
||||
mergedGroups = reader.Get<string>("Groups");
|
||||
}
|
||||
if (groupsNew != "")
|
||||
groupsNew += ",";
|
||||
groupsNew += groups;
|
||||
|
||||
int q = database.Query("UPDATE Regions SET Groups=@0 WHERE RegionName=@1 AND WorldID=@2", groupsNew,
|
||||
string[] groups = mergedGroups.Split(',');
|
||||
// Is the group already allowed to the region?
|
||||
if (groups.Contains(groupName))
|
||||
return true;
|
||||
|
||||
if (mergedGroups != "")
|
||||
mergedGroups += ",";
|
||||
mergedGroups += groupName;
|
||||
|
||||
int q = database.Query("UPDATE Regions SET Groups=@0 WHERE RegionName=@1 AND WorldID=@2", mergedGroups,
|
||||
regionName, Main.worldID.ToString());
|
||||
|
||||
Region r = GetRegionByName(regionName);
|
||||
if (r != null)
|
||||
{
|
||||
r.SetAllowedGroups(groupsNew);
|
||||
r.SetAllowedGroups(mergedGroups);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Data;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
|
@ -112,7 +113,7 @@ namespace TShockAPI.DB
|
|||
try
|
||||
{
|
||||
if ((X != 0) && ( Y !=0)) //invalid pos!
|
||||
database.Query("UPDATE RememberedPos SET X = @0, Y = @1, IP = @2 WHERE Name = @3 AND WorldID = @4;", X, Y, IP, name, Main.worldID.ToString());
|
||||
database.Query("UPDATE RememberedPos SET X = @0, Y = @1, IP = @2, WorldID = @3 WHERE Name = @4;", X, Y, IP, Main.worldID.ToString(), name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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 MySql.Data.MySqlClient;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Data;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Collections.Generic;
|
||||
using System.Data;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,9 +15,9 @@ 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.Data;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
|
@ -38,7 +38,8 @@ namespace TShockAPI.DB
|
|||
new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true},
|
||||
new SqlColumn("Password", MySqlDbType.VarChar, 128),
|
||||
new SqlColumn("Usergroup", MySqlDbType.Text),
|
||||
new SqlColumn("IP", MySqlDbType.VarChar, 16)
|
||||
new SqlColumn("LastAccessed", MySqlDbType.Text),
|
||||
new SqlColumn("KnownIPs", MySqlDbType.Text)
|
||||
);
|
||||
var creator = new SqlTableCreator(db,
|
||||
db.GetSqlType() == SqlType.Sqlite
|
||||
|
|
@ -59,8 +60,8 @@ namespace TShockAPI.DB
|
|||
int ret;
|
||||
try
|
||||
{
|
||||
ret = database.Query("INSERT INTO Users (Username, Password, UserGroup, IP) VALUES (@0, @1, @2, @3);", user.Name,
|
||||
TShock.Utils.HashPassword(user.Password), user.Group, user.Address);
|
||||
ret = database.Query("INSERT INTO Users (Username, Password, UserGroup) VALUES (@0, @1, @2);", user.Name,
|
||||
TShock.Utils.HashPassword(user.Password), user.Group);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -82,18 +83,10 @@ namespace TShockAPI.DB
|
|||
{
|
||||
try
|
||||
{
|
||||
int affected = -1;
|
||||
if (!string.IsNullOrEmpty(user.Address))
|
||||
{
|
||||
affected = database.Query("DELETE FROM Users WHERE IP=@0", user.Address);
|
||||
}
|
||||
else
|
||||
{
|
||||
affected = database.Query("DELETE FROM Users WHERE Username=@0", user.Name);
|
||||
}
|
||||
int affected = database.Query("DELETE FROM Users WHERE Username=@0", user.Name);
|
||||
|
||||
if (affected < 1)
|
||||
throw new UserNotExistException(string.IsNullOrEmpty(user.Address) ? user.Name : user.Address);
|
||||
throw new UserNotExistException(user.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -101,7 +94,6 @@ namespace TShockAPI.DB
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Hashed Password for a given username
|
||||
/// </summary>
|
||||
|
|
@ -150,6 +142,19 @@ namespace TShockAPI.DB
|
|||
}
|
||||
}
|
||||
|
||||
public void UpdateLogin(User user)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (database.Query("UPDATE Users SET LastAccessed = @0, KnownIps = @1 WHERE Username = @2;", DateTime.Now.ToString("G"), user.KnownIps, user.Name) == 0)
|
||||
throw new UserNotExistException(user.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new UserManagerException("UpdateLogin SQL returned an error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetUserID(string username)
|
||||
{
|
||||
try
|
||||
|
|
@ -169,53 +174,6 @@ namespace TShockAPI.DB
|
|||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Group for a ip from the database
|
||||
/// </summary>
|
||||
/// <param name="ply">string ip</param>
|
||||
public Group GetGroupForIP(string ip)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var reader = database.QueryReader("SELECT * FROM Users WHERE IP=@0", ip))
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
string group = reader.Get<string>("UserGroup");
|
||||
return TShock.Utils.GetGroup(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex);
|
||||
}
|
||||
return TShock.Utils.GetGroup(TShock.Config.DefaultGuestGroupName);
|
||||
}
|
||||
|
||||
public Group GetGroupForIPExpensive(string ip)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var reader = database.QueryReader("SELECT IP, UserGroup FROM Users"))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
if (TShock.Utils.GetIPv4Address(reader.Get<string>("IP")) == ip)
|
||||
{
|
||||
return TShock.Utils.GetGroup(reader.Get<string>("UserGroup"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex);
|
||||
}
|
||||
return TShock.Utils.GetGroup(TShock.Config.DefaultGuestGroupName);
|
||||
}
|
||||
|
||||
|
||||
public User GetUserByName(string name)
|
||||
{
|
||||
try
|
||||
|
|
@ -240,18 +198,6 @@ namespace TShockAPI.DB
|
|||
}
|
||||
}
|
||||
|
||||
public User GetUserByIP(string ip)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetUser(new User {Address = ip});
|
||||
}
|
||||
catch (UserManagerException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public User GetUser(User user)
|
||||
{
|
||||
bool multiple = false;
|
||||
|
|
@ -264,18 +210,12 @@ namespace TShockAPI.DB
|
|||
arg = user.ID;
|
||||
type = "id";
|
||||
}
|
||||
else if (string.IsNullOrEmpty(user.Address))
|
||||
else
|
||||
{
|
||||
query = "SELECT * FROM Users WHERE Username=@0";
|
||||
arg = user.Name;
|
||||
type = "name";
|
||||
}
|
||||
else
|
||||
{
|
||||
query = "SELECT * FROM Users WHERE IP=@0";
|
||||
arg = user.Address;
|
||||
type = "ip";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -298,7 +238,7 @@ namespace TShockAPI.DB
|
|||
if (multiple)
|
||||
throw new UserManagerException(String.Format("Multiple users found for {0} '{1}'", type, arg));
|
||||
|
||||
throw new UserNotExistException(string.IsNullOrEmpty(user.Address) ? user.Name : user.Address);
|
||||
throw new UserNotExistException(user.Name);
|
||||
}
|
||||
|
||||
public List<User> GetUsers()
|
||||
|
|
@ -328,7 +268,8 @@ namespace TShockAPI.DB
|
|||
user.Group = result.Get<string>("Usergroup");
|
||||
user.Password = result.Get<string>("Password");
|
||||
user.Name = result.Get<string>("Username");
|
||||
user.Address = result.Get<string>("IP");
|
||||
user.LastAccessed = result.Get<string>("LastAccessed");
|
||||
user.KnownIps = result.Get<string>("KnownIps");
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
|
@ -339,22 +280,25 @@ namespace TShockAPI.DB
|
|||
public string Name { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string Group { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string LastAccessed { get; set; }
|
||||
public string KnownIps { get; set; }
|
||||
|
||||
public User(string ip, string name, string pass, string group)
|
||||
public User(string name, string pass, string group, string last, string known)
|
||||
{
|
||||
Address = ip;
|
||||
Name = name;
|
||||
Password = pass;
|
||||
Group = group;
|
||||
LastAccessed = last;
|
||||
KnownIps = known;
|
||||
}
|
||||
|
||||
public User()
|
||||
{
|
||||
Address = "";
|
||||
Name = "";
|
||||
Password = "";
|
||||
Group = "";
|
||||
LastAccessed = "";
|
||||
KnownIps = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Data;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Data;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Text;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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;
|
||||
|
||||
namespace TShockAPI
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,22 @@
|
|||
/* GeoIPCountry.cs
|
||||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* GeoIPCountry.cs
|
||||
*
|
||||
* Copyright (C) 2008 MaxMind, Inc. All Rights Reserved.
|
||||
*
|
||||
|
|
@ -16,24 +34,6 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,13 +15,16 @@ 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.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Streams;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using TShockAPI.DB;
|
||||
using Terraria;
|
||||
using TShockAPI.Net;
|
||||
|
||||
|
|
@ -86,13 +89,18 @@ namespace TShockAPI
|
|||
/// Did the tile get destroyed successfully.
|
||||
/// </summary>
|
||||
public bool Fail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used when a tile is placed to denote a subtype of tile. (e.g. for tile id 21: Chest = 0, Gold Chest = 1)
|
||||
/// </summary>
|
||||
public byte Style { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TileEdit - called when a tile is placed or destroyed
|
||||
/// </summary>
|
||||
public static HandlerList<TileEditEventArgs> TileEdit;
|
||||
private static bool OnTileEdit(TSPlayer ply, int x, int y, byte type, byte editType, bool fail)
|
||||
private static bool OnTileEdit(TSPlayer ply, int x, int y, byte type, byte editType, bool fail, byte style)
|
||||
{
|
||||
if (TileEdit == null)
|
||||
return false;
|
||||
|
|
@ -104,7 +112,8 @@ namespace TShockAPI
|
|||
Y = y,
|
||||
Type = type,
|
||||
EditType = editType,
|
||||
Fail = fail
|
||||
Fail = fail,
|
||||
Style = style
|
||||
};
|
||||
TileEdit.Invoke(null, args);
|
||||
return args.Handled;
|
||||
|
|
@ -1189,6 +1198,14 @@ namespace TShockAPI
|
|||
byte prefix = args.Data.ReadInt8();
|
||||
short type = args.Data.ReadInt16();
|
||||
|
||||
// Players send a slot update packet for each inventory slot right after they've joined.
|
||||
bool bypassTrashCanCheck = false;
|
||||
if (plr == args.Player.Index && !args.Player.HasSentInventory && slot == NetItem.maxNetInventory)
|
||||
{
|
||||
args.Player.HasSentInventory = true;
|
||||
bypassTrashCanCheck = true;
|
||||
}
|
||||
|
||||
if (OnPlayerSlot(plr, slot, stack, prefix, type))
|
||||
return true;
|
||||
|
||||
|
|
@ -1202,6 +1219,7 @@ namespace TShockAPI
|
|||
return true;
|
||||
}
|
||||
|
||||
// Garabage? Or will it cause some internal initialization or whatever?
|
||||
var item = new Item();
|
||||
item.netDefaults(type);
|
||||
item.Prefix(prefix);
|
||||
|
|
@ -1210,6 +1228,13 @@ namespace TShockAPI
|
|||
{
|
||||
args.Player.PlayerData.StoreSlot(slot, type, prefix, stack);
|
||||
}
|
||||
else if (
|
||||
TShock.Config.ServerSideInventory && TShock.Config.DisableLoginBeforeJoin && !bypassTrashCanCheck &&
|
||||
args.Player.HasSentInventory && !args.Player.Group.HasPermission(Permissions.bypassinventorychecks)
|
||||
) {
|
||||
// The player might have moved an item to their trash can before they performed a single login attempt yet.
|
||||
args.Player.IgnoreActionsForClearingTrashCan = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1226,7 +1251,7 @@ namespace TShockAPI
|
|||
if (args.Player.FirstMaxHP == 0)
|
||||
args.Player.FirstMaxHP = max;
|
||||
|
||||
if (max > 400 && max > args.Player.FirstMaxHP)
|
||||
if (max > TShock.Config.MaxHealth && max > args.Player.FirstMaxHP)
|
||||
{
|
||||
TShock.Utils.ForceKick(args.Player, "Hacked Client Detected.", true);
|
||||
return false;
|
||||
|
|
@ -1252,7 +1277,7 @@ namespace TShockAPI
|
|||
if (args.Player.FirstMaxMP == 0)
|
||||
args.Player.FirstMaxMP = max;
|
||||
|
||||
if (max > 400 && max > args.Player.FirstMaxMP)
|
||||
if (max > TShock.Config.MaxMana && max > args.Player.FirstMaxMP)
|
||||
{
|
||||
TShock.Utils.ForceKick(args.Player, "Hacked Client Detected.", true);
|
||||
return false;
|
||||
|
|
@ -1281,12 +1306,6 @@ namespace TShockAPI
|
|||
TShock.Utils.ForceKick(args.Player, "Empty Name.", true);
|
||||
return true;
|
||||
}
|
||||
var ban = TShock.Bans.GetBanByName(name);
|
||||
if (ban != null)
|
||||
{
|
||||
TShock.Utils.ForceKick(args.Player, string.Format("You are banned: {0}", ban.Reason), true);
|
||||
return true;
|
||||
}
|
||||
if (args.Player.ReceivedInfo)
|
||||
{
|
||||
return true;
|
||||
|
|
@ -1336,6 +1355,10 @@ namespace TShockAPI
|
|||
return true;
|
||||
|
||||
string password = Encoding.UTF8.GetString(args.Data.ReadBytes((int) (args.Data.Length - args.Data.Position - 1)));
|
||||
|
||||
if (Hooks.PlayerHooks.OnPlayerPreLogin(args.Player, args.Player.Name, password))
|
||||
return true;
|
||||
|
||||
var user = TShock.Users.GetUserByName(args.Player.Name);
|
||||
if (user != null && !TShock.Config.DisableLoginBeforeJoin)
|
||||
{
|
||||
|
|
@ -1359,11 +1382,13 @@ namespace TShockAPI
|
|||
}
|
||||
else if (!TShock.CheckInventory(args.Player))
|
||||
{
|
||||
args.Player.LoginFailsBySsi = true;
|
||||
args.Player.SendMessage("Login Failed, Please fix the above errors then /login again.", Color.Cyan);
|
||||
args.Player.IgnoreActionsForClearingTrashCan = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
args.Player.LoginFailsBySsi = false;
|
||||
|
||||
if (group.HasPermission(Permissions.ignorestackhackdetection))
|
||||
args.Player.IgnoreActionsForCheating = "none";
|
||||
|
|
@ -1372,6 +1397,7 @@ namespace TShockAPI
|
|||
args.Player.IgnoreActionsForDisabledArmor = "none";
|
||||
|
||||
args.Player.Group = group;
|
||||
args.Player.tempGroup = null;
|
||||
args.Player.UserAccountName = args.Player.Name;
|
||||
args.Player.UserID = TShock.Users.GetUserID(args.Player.UserAccountName);
|
||||
args.Player.IsLoggedIn = true;
|
||||
|
|
@ -1384,7 +1410,7 @@ namespace TShockAPI
|
|||
}
|
||||
args.Player.SendMessage("Authenticated as " + args.Player.Name + " successfully.", Color.LimeGreen);
|
||||
Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user " + args.Player.Name + ".");
|
||||
Hooks.PlayerLoginEvent.OnPlayerLogin(args.Player);
|
||||
Hooks.PlayerHooks.OnPlayerPostLogin(args.Player);
|
||||
return true;
|
||||
}
|
||||
TShock.Utils.ForceKick(args.Player, "Invalid user account password.", true);
|
||||
|
|
@ -1418,7 +1444,7 @@ namespace TShockAPI
|
|||
TShock.Utils.ForceKick(args.Player, "Blank name.", true);
|
||||
return true;
|
||||
}
|
||||
if (TShock.HackedHealth(args.Player) && !args.Player.Group.HasPermission(Permissions.ignorestathackdetection))
|
||||
if (TShock.HackedStats(args.Player) && !args.Player.Group.HasPermission(Permissions.ignorestathackdetection))
|
||||
{
|
||||
TShock.Utils.ForceKick(args.Player, "You have hacked health/mana, please use a different character.", true);
|
||||
return true;
|
||||
|
|
@ -1443,13 +1469,15 @@ namespace TShockAPI
|
|||
Log.Info(string.Format("{0} ({1}) from '{2}' group from '{3}' joined. ({4}/{5})", args.Player.Name, args.Player.IP,
|
||||
args.Player.Group.Name, args.Player.Country, TShock.Utils.ActivePlayers(),
|
||||
TShock.Config.MaxSlots));
|
||||
TShock.Utils.Broadcast(string.Format("{0} ({1}) has joined.", args.Player.Name, args.Player.Country), Color.Yellow);
|
||||
if (!args.Player.SilentJoinInProgress)
|
||||
TShock.Utils.Broadcast(string.Format("{0} ({1}) has joined.", args.Player.Name, args.Player.Country), Color.Yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Info(string.Format("{0} ({1}) from '{2}' group joined. ({3}/{4})", args.Player.Name, args.Player.IP,
|
||||
args.Player.Group.Name, TShock.Utils.ActivePlayers(), TShock.Config.MaxSlots));
|
||||
TShock.Utils.Broadcast(args.Player.Name + " has joined.", Color.Yellow);
|
||||
if (!args.Player.SilentJoinInProgress)
|
||||
TShock.Utils.Broadcast(args.Player.Name + " has joined.", Color.Yellow);
|
||||
}
|
||||
|
||||
if (TShock.Config.DisplayIPToAdmins)
|
||||
|
|
@ -1651,10 +1679,12 @@ namespace TShockAPI
|
|||
var tileX = args.Data.ReadInt32();
|
||||
var tileY = args.Data.ReadInt32();
|
||||
var tiletype = args.Data.ReadInt8();
|
||||
var fail = args.Data.ReadBoolean();
|
||||
if (OnTileEdit(args.Player, tileX, tileY, tiletype, type, fail))
|
||||
var fail = tiletype == 1;
|
||||
var style = args.Data.ReadInt8();
|
||||
|
||||
if (OnTileEdit(args.Player, tileX, tileY, tiletype, type, fail, style))
|
||||
return true;
|
||||
if (!TShock.Utils.TileValid(tileX, tileY))
|
||||
if (!TShock.Utils.TilePlacementValid(tileX, tileY))
|
||||
return false;
|
||||
|
||||
if (args.Player.Dead && TShock.Config.PreventDeadModification)
|
||||
|
|
@ -1662,18 +1692,63 @@ namespace TShockAPI
|
|||
|
||||
if (args.Player.AwaitingName)
|
||||
{
|
||||
var protectedregions = TShock.Regions.InAreaRegionName(tileX, tileY);
|
||||
if (protectedregions.Count == 0)
|
||||
Debug.Assert(args.Player.AwaitingNameParameters != null);
|
||||
|
||||
bool includeUnprotected = false;
|
||||
bool includeZIndexes = false;
|
||||
bool persistentMode = false;
|
||||
foreach (string parameter in args.Player.AwaitingNameParameters)
|
||||
{
|
||||
args.Player.SendMessage("Region is not protected", Color.Yellow);
|
||||
if (parameter.Equals("-u", StringComparison.InvariantCultureIgnoreCase))
|
||||
includeUnprotected = true;
|
||||
if (parameter.Equals("-z", StringComparison.InvariantCultureIgnoreCase))
|
||||
includeZIndexes = true;
|
||||
if (parameter.Equals("-p", StringComparison.InvariantCultureIgnoreCase))
|
||||
persistentMode = true;
|
||||
}
|
||||
|
||||
List<string> outputRegions = new List<string>();
|
||||
foreach (Region region in TShock.Regions.Regions.OrderBy(r => r.Z).Reverse())
|
||||
{
|
||||
if (!includeUnprotected && !region.DisableBuild)
|
||||
continue;
|
||||
if (tileX < region.Area.Left || tileX > region.Area.Right)
|
||||
continue;
|
||||
if (tileY < region.Area.Top || tileY > region.Area.Bottom)
|
||||
continue;
|
||||
|
||||
string format = "{1}";
|
||||
if (includeZIndexes)
|
||||
format = "{1} (z:{0})";
|
||||
|
||||
outputRegions.Add(string.Format(format, region.Z, region.Name));
|
||||
}
|
||||
|
||||
if (outputRegions.Count == 0)
|
||||
{
|
||||
if (includeUnprotected)
|
||||
args.Player.SendMessage("There are no regions at this point.", Color.Yellow);
|
||||
else
|
||||
args.Player.SendMessage("There are no regions at this point or they are not protected.", Color.Yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
string regionlist = string.Join(",", protectedregions.ToArray());
|
||||
args.Player.SendMessage("Region Name(s): " + regionlist, Color.Yellow);
|
||||
if (includeUnprotected)
|
||||
args.Player.SendSuccessMessage("Regions at this point:");
|
||||
else
|
||||
args.Player.SendSuccessMessage("Protected regions at this point:");
|
||||
|
||||
foreach (string line in PaginationTools.BuildLinesFromTerms(outputRegions))
|
||||
args.Player.SendMessage(line, Color.White);
|
||||
}
|
||||
|
||||
if (!persistentMode)
|
||||
{
|
||||
args.Player.AwaitingName = false;
|
||||
args.Player.AwaitingNameParameters = null;
|
||||
}
|
||||
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
args.Player.AwaitingName = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1687,22 +1762,63 @@ namespace TShockAPI
|
|||
return true;
|
||||
}
|
||||
|
||||
if (type == 1 || type == 3)
|
||||
byte[] rightClickKill = new byte[] { 4, 13, 33, 49, 50, 128};
|
||||
Item selectedItem = args.TPlayer.inventory[args.TPlayer.selectedItem];
|
||||
if (type == 0 && Main.tile[tileX, tileY].type != 127 && !Main.tileCut[Main.tile[tileX, tileY].type] && !rightClickKill.Contains(Main.tile[tileX, tileY].type))
|
||||
{
|
||||
if (tiletype >= ((type == 1) ? Main.maxTileSets : Main.maxWallTypes))
|
||||
// If the tile is an axe tile and they aren't selecting an axe, they're hacking.
|
||||
if (Main.tileAxe[Main.tile[tileX, tileY].type] && selectedItem.axe == 0)
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
// If the tile is a hammer tile and they aren't selecting an hammer, they're hacking.
|
||||
else if (Main.tileHammer[Main.tile[tileX, tileY].type] && selectedItem.hammer == 0)
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
// If the tile is a pickaxe tile and they aren't selecting an pickaxe, they're hacking.
|
||||
else if ((!Main.tileAxe[Main.tile[tileX, tileY].type] && !Main.tileHammer[Main.tile[tileX, tileY].type]) && selectedItem.pick == 0)
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (type == 2)
|
||||
{
|
||||
// If they aren't selecting an hammer, they're hacking.
|
||||
if (selectedItem.hammer == 0)
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (type == 1 || type == 3)
|
||||
{
|
||||
if (type == 1 && TShock.Config.PreventInvalidPlaceStyle && ((tiletype == 4 && style > 8) ||
|
||||
(tiletype == 13 && style > 4) || (tiletype == 15 && style > 1) || (tiletype == 21 && style > 6) ||
|
||||
(tiletype == 82 && style > 5) || (tiletype == 91 && style > 3) || (tiletype == 105 && style > 42) ||
|
||||
(tiletype == 135 && style > 3) || (tiletype == 139 && style > 12) || (tiletype == 144 && style > 2) ||
|
||||
(tiletype == 149 && style > 2)))
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
// If they aren't selecting the item which creates the tile or wall, they're hacking.
|
||||
if (tiletype != 127 && tiletype != (type == 1 ? selectedItem.createTile : selectedItem.createWall))
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
if (TShock.Itembans.ItemIsBanned(selectedItem.name, args.Player) || tiletype >= (type == 1 ? Main.maxTileSets : Main.maxWallTypes))
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
if (type == 1 && (tiletype == 29 || tiletype == 97) && TShock.Config.ServerSideInventory && TShock.Config.DisablePiggybanksOnSSI)
|
||||
{
|
||||
args.Player.SendMessage("You cannot place this tile, server side inventory is enabled.", Color.Red);
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
if (tiletype == 48 && !args.Player.Group.HasPermission(Permissions.usebanneditem) &&
|
||||
TShock.Itembans.ItemIsBanned("Spike", args.Player))
|
||||
{
|
||||
args.Player.Disable("Used banned spikes without permission.");
|
||||
args.Player.SendMessage("You cannot place this tile because server side inventory is enabled.", Color.Red);
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1710,21 +1826,32 @@ namespace TShockAPI
|
|||
{
|
||||
if (TShock.Utils.MaxChests())
|
||||
{
|
||||
args.Player.SendMessage("Reached the world's max chest limit, unable to place more.", Color.Red);
|
||||
args.Player.SendMessage("The world's chest limit has been reached - unable to place more.", Color.Red);
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
if ((TShock.Utils.TileValid(tileX, tileY + 1) && Main.tile[tileX, tileY + 1].type == 138) ||
|
||||
(TShock.Utils.TileValid(tileX + 1, tileY + 1) && Main.tile[tileX + 1, tileY + 1].type == 138))
|
||||
if ((TShock.Utils.TilePlacementValid(tileX, tileY + 1) && Main.tile[tileX, tileY + 1].type == 138) ||
|
||||
(TShock.Utils.TilePlacementValid(tileX + 1, tileY + 1) && Main.tile[tileX + 1, tileY + 1].type == 138))
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (tiletype == 141 && !args.Player.Group.HasPermission(Permissions.usebanneditem) &&
|
||||
TShock.Itembans.ItemIsBanned("Explosives", args.Player))
|
||||
}
|
||||
else if (type == 5)
|
||||
{
|
||||
// If they aren't selecting the wrench, they're hacking.
|
||||
if (args.TPlayer.inventory[args.TPlayer.selectedItem].type != 509)
|
||||
{
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (type == 6)
|
||||
{
|
||||
// If they aren't selecting the wire cutter, they're hacking.
|
||||
if (args.TPlayer.inventory[args.TPlayer.selectedItem].type != 510)
|
||||
{
|
||||
args.Player.Disable("Used banned explosives tile without permission.");
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2040,17 +2167,18 @@ namespace TShockAPI
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!TShock.Config.IgnoreProjUpdate && TShock.CheckProjectilePermission(args.Player, index, type))
|
||||
bool hasPermission = !TShock.CheckProjectilePermission(args.Player, index, type);
|
||||
if (!TShock.Config.IgnoreProjUpdate && !hasPermission)
|
||||
{
|
||||
if (type == 100)
|
||||
{ //fix for skele prime
|
||||
Log.Debug("Skeletron Prime's death laser ignored for cheat detection..");
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Player.Disable("Does not have projectile permission to update projectile.");
|
||||
args.Player.RemoveProjectile(ident, owner);
|
||||
}
|
||||
if (type == 100)
|
||||
{ //fix for skele prime
|
||||
Log.Debug("Skeletron Prime's death laser ignored for cheat detection..");
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Player.Disable("Does not have projectile permission to update projectile.");
|
||||
args.Player.RemoveProjectile(ident, owner);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2069,14 +2197,22 @@ namespace TShockAPI
|
|||
|
||||
if (!args.Player.Group.HasPermission(Permissions.ignoreprojectiledetection))
|
||||
{
|
||||
if ((type ==90) && (TShock.Config.ProjIgnoreShrapnel))// ignore shrapnel
|
||||
{
|
||||
Log.Debug("Ignoring shrapnel per config..");
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Player.ProjectileThreshold++;
|
||||
}
|
||||
if ((type == 90) && (TShock.Config.ProjIgnoreShrapnel))// ignore shrapnel
|
||||
{
|
||||
Log.Debug("Ignoring shrapnel per config..");
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Player.ProjectileThreshold++;
|
||||
}
|
||||
}
|
||||
|
||||
// force all explosives server-side.
|
||||
if (hasPermission && (type == 28 || type == 29 || type == 37))
|
||||
{
|
||||
args.Player.RemoveProjectile(ident, owner);
|
||||
Projectile.NewProjectile(pos.X, pos.Y, vel.X, vel.Y, type, dmg, knockback);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -2192,18 +2328,36 @@ namespace TShockAPI
|
|||
bucket = 2;
|
||||
}
|
||||
|
||||
if (lava && bucket != 2 && !args.Player.Group.HasPermission(Permissions.usebanneditem) &&
|
||||
TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player))
|
||||
{
|
||||
args.Player.Disable("Using banned lava bucket without permissions.");
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
if(lava && bucket != 2)
|
||||
{
|
||||
args.Player.SendErrorMessage("You do not have permission to perform this action.");
|
||||
args.Player.Disable("Spreading lava without holding a lava bucket");
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(lava && (!args.Player.Group.HasPermission(Permissions.usebanneditem) &&
|
||||
TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player)))
|
||||
{
|
||||
args.Player.SendErrorMessage("You do not have permission to perform this action.");
|
||||
args.Player.Disable("Using banned lava bucket without permissions");
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!lava && bucket != 1 && !args.Player.Group.HasPermission(Permissions.usebanneditem) &&
|
||||
TShock.Itembans.ItemIsBanned("Water Bucket", args.Player))
|
||||
if (!lava && bucket != 1)
|
||||
{
|
||||
args.Player.SendErrorMessage("You do not have permission to perform this action.");
|
||||
args.Player.Disable("Spreading water without holding a water bucket");
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!lava && (!args.Player.Group.HasPermission(Permissions.usebanneditem) &&
|
||||
TShock.Itembans.ItemIsBanned("Water Bucket", args.Player)))
|
||||
{
|
||||
args.Player.Disable("Using banned water bucket without permissions.");
|
||||
args.Player.SendErrorMessage("You do not have permission to perform this action.");
|
||||
args.Player.Disable("Using banned water bucket without permissions");
|
||||
args.Player.SendTileSquare(tileX, tileY);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2286,7 +2440,7 @@ namespace TShockAPI
|
|||
{
|
||||
if (TShock.Config.BanOnMediumcoreDeath)
|
||||
{
|
||||
if (!TShock.Utils.Ban(args.Player, TShock.Config.MediumcoreBanReason))
|
||||
if (!TShock.Utils.Ban(args.Player, TShock.Config.MediumcoreBanReason, false, "mediumcore-death"))
|
||||
TShock.Utils.ForceKick(args.Player, "Death results in a ban, but can't ban you.", true);
|
||||
}
|
||||
else
|
||||
|
|
@ -2782,7 +2936,7 @@ namespace TShockAPI
|
|||
break;
|
||||
}
|
||||
|
||||
TShock.Utils.SendLogs(string.Format("{0} summoned {1}", args.Player.Name, boss), Color.Red);
|
||||
TShock.Utils.SendLogs(string.Format("{0} summoned {1}", args.Player.Name, boss), Color.PaleVioletRed, args.Player);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -28,7 +29,7 @@ namespace TShockAPI
|
|||
/// <summary>
|
||||
/// Default chat color.
|
||||
/// </summary>
|
||||
public const string defaultChatColor = "255.255.255";
|
||||
public const string defaultChatColor = "255,255,255";
|
||||
|
||||
/// <summary>
|
||||
/// List of permissions available to the group.
|
||||
|
|
@ -151,6 +152,7 @@ namespace TShockAPI
|
|||
public byte G = 255;
|
||||
public byte B = 255;
|
||||
|
||||
public static Group DefaultGroup = null;
|
||||
#if COMPAT_SIGS
|
||||
[Obsolete("This constructor is for signature compatibility for external code only")]
|
||||
public Group(string groupname, Group parentgroup, string chatcolor)
|
||||
|
|
@ -204,7 +206,7 @@ namespace TShockAPI
|
|||
return true;
|
||||
if (traversed.Contains(cur))
|
||||
{
|
||||
throw new Exception("Infinite group parenting ({0})".SFormat(cur.Name));
|
||||
throw new InvalidOperationException("Infinite group parenting ({0})".SFormat(cur.Name));
|
||||
}
|
||||
traversed.Add(cur);
|
||||
cur = cur.Parent;
|
||||
|
|
@ -271,6 +273,26 @@ namespace TShockAPI
|
|||
}
|
||||
permissions.Remove(permission);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns all fields of this instance to another.
|
||||
/// </summary>
|
||||
/// <param name="otherGroup">The other instance.</param>
|
||||
public void AssignTo(Group otherGroup)
|
||||
{
|
||||
otherGroup.Name = Name;
|
||||
otherGroup.Parent = Parent;
|
||||
otherGroup.Prefix = Prefix;
|
||||
otherGroup.Suffix = Suffix;
|
||||
otherGroup.R = R;
|
||||
otherGroup.G = G;
|
||||
otherGroup.B = B;
|
||||
otherGroup.Permissions = Permissions;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return this.Name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -298,4 +320,4 @@ namespace TShockAPI
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,11 +15,11 @@ 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.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
|
|
|
|||
43
TShockAPI/Hooks/GeneralHooks.cs
Normal file
43
TShockAPI/Hooks/GeneralHooks.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace TShockAPI.Hooks
|
||||
{
|
||||
public class ReloadEventArgs
|
||||
{
|
||||
public TSPlayer Player { get; set; }
|
||||
public ReloadEventArgs(TSPlayer ply)
|
||||
{
|
||||
Player = ply;
|
||||
}
|
||||
}
|
||||
|
||||
public class GeneralHooks
|
||||
{
|
||||
public delegate void ReloadEventD(ReloadEventArgs e);
|
||||
public static event ReloadEventD ReloadEvent;
|
||||
|
||||
public static void OnReloadEvent(TSPlayer ply)
|
||||
{
|
||||
if(ReloadEvent == null)
|
||||
return;
|
||||
|
||||
ReloadEvent(new ReloadEventArgs(ply));
|
||||
}
|
||||
}
|
||||
}
|
||||
98
TShockAPI/Hooks/PlayerHooks.cs
Normal file
98
TShockAPI/Hooks/PlayerHooks.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace TShockAPI.Hooks
|
||||
{
|
||||
public class PlayerPostLoginEventArgs
|
||||
{
|
||||
public TSPlayer Player { get; set; }
|
||||
public PlayerPostLoginEventArgs(TSPlayer ply)
|
||||
{
|
||||
Player = ply;
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerPreLoginEventArgs : HandledEventArgs
|
||||
{
|
||||
public TSPlayer Player { get; set; }
|
||||
public string LoginName { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
||||
public class PlayerCommandEventArgs : HandledEventArgs
|
||||
{
|
||||
public TSPlayer Player { get; set; }
|
||||
public string CommandName { get; set; }
|
||||
public string CommandText { get; set; }
|
||||
public List<string> Parameters { get; set; }
|
||||
}
|
||||
|
||||
public static class PlayerHooks
|
||||
{
|
||||
public delegate void PlayerPostLoginD(PlayerPostLoginEventArgs e);
|
||||
public static event PlayerPostLoginD PlayerPostLogin;
|
||||
|
||||
public delegate void PlayerPreLoginD(PlayerPreLoginEventArgs e);
|
||||
public static event PlayerPreLoginD PlayerPreLogin;
|
||||
|
||||
public delegate void PlayerCommandD(PlayerCommandEventArgs e);
|
||||
public static event PlayerCommandD PlayerCommand;
|
||||
|
||||
public static void OnPlayerPostLogin(TSPlayer ply)
|
||||
{
|
||||
if(PlayerPostLogin == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerPostLoginEventArgs args = new PlayerPostLoginEventArgs(ply);
|
||||
PlayerPostLogin(args);
|
||||
}
|
||||
|
||||
public static bool OnPlayerCommand(TSPlayer player, string cmdName, string cmdText, List<string> args)
|
||||
{
|
||||
if (PlayerCommand == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
PlayerCommandEventArgs playerCommandEventArgs = new PlayerCommandEventArgs()
|
||||
{
|
||||
Player = player,
|
||||
CommandName = cmdName,
|
||||
CommandText = cmdText,
|
||||
Parameters = args
|
||||
|
||||
};
|
||||
PlayerCommand(playerCommandEventArgs);
|
||||
return playerCommandEventArgs.Handled;
|
||||
}
|
||||
|
||||
public static bool OnPlayerPreLogin(TSPlayer ply, string name, string pass)
|
||||
{
|
||||
if (PlayerPreLogin == null)
|
||||
return false;
|
||||
|
||||
var args = new PlayerPreLoginEventArgs {Player = ply, LoginName = name, Password = pass};
|
||||
PlayerPreLogin(args);
|
||||
return args.Handled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace TShockAPI.Hooks
|
||||
{
|
||||
class PlayerLoginEventArgs
|
||||
{
|
||||
public TSPlayer Player { get; set; }
|
||||
public PlayerLoginEventArgs(TSPlayer ply)
|
||||
{
|
||||
Player = ply;
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerLoginEvent
|
||||
{
|
||||
public delegate void PlayerLoginD(PlayerLoginEventArgs e);
|
||||
public static event PlayerLoginD PlayerLogin;
|
||||
public static void OnPlayerLogin(TSPlayer ply)
|
||||
{
|
||||
if(PlayerLogin == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerLoginEventArgs args = new PlayerLoginEventArgs(ply);
|
||||
PlayerLogin(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.IO;
|
||||
|
||||
namespace TShockAPI
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
|
@ -72,6 +73,16 @@ namespace TShockAPI
|
|||
Write(message, LogLevel.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to the log file.
|
||||
/// </summary>
|
||||
/// <param name="format">The format of the message to be written.</param>
|
||||
/// <param name="args">The format arguments.</param>
|
||||
public static void Data(String format, params String[] args)
|
||||
{
|
||||
Data(String.Format(format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an error to the log file.
|
||||
/// </summary>
|
||||
|
|
@ -81,6 +92,16 @@ namespace TShockAPI
|
|||
Write(message, LogLevel.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an error to the log file.
|
||||
/// </summary>
|
||||
/// <param name="format">The format of the message to be written.</param>
|
||||
/// <param name="args">The format arguments.</param>
|
||||
public static void Error(String format, params String[] args)
|
||||
{
|
||||
Error(String.Format(format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an error to the log file.
|
||||
/// </summary>
|
||||
|
|
@ -93,6 +114,16 @@ namespace TShockAPI
|
|||
Write(message, LogLevel.Error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an error to the log file.
|
||||
/// </summary>
|
||||
/// <param name="format">The format of the message to be written.</param>
|
||||
/// <param name="args">The format arguments.</param>
|
||||
public static void ConsoleError(String format, params String[] args)
|
||||
{
|
||||
ConsoleError(String.Format(format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a warning to the log file.
|
||||
/// </summary>
|
||||
|
|
@ -102,6 +133,16 @@ namespace TShockAPI
|
|||
Write(message, LogLevel.Warning);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a warning to the log file.
|
||||
/// </summary>
|
||||
/// <param name="format">The format of the message to be written.</param>
|
||||
/// <param name="args">The format arguments.</param>
|
||||
public static void Warn(String format, params String[] args)
|
||||
{
|
||||
Warn(String.Format(format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an informative string to the log file.
|
||||
/// </summary>
|
||||
|
|
@ -111,6 +152,16 @@ namespace TShockAPI
|
|||
Write(message, LogLevel.Info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an informative string to the log file.
|
||||
/// </summary>
|
||||
/// <param name="format">The format of the message to be written.</param>
|
||||
/// <param name="args">The format arguments.</param>
|
||||
public static void Info(String format, params String[] args)
|
||||
{
|
||||
Info(String.Format(format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an informative string to the log file. Also outputs to the console.
|
||||
/// </summary>
|
||||
|
|
@ -123,6 +174,16 @@ namespace TShockAPI
|
|||
Write(message, LogLevel.Info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an informative string to the log file. Also outputs to the console.
|
||||
/// </summary>
|
||||
/// <param name="format">The format of the message to be written.</param>
|
||||
/// <param name="args">The format arguments.</param>
|
||||
public static void ConsoleInfo(String format, params String[] args)
|
||||
{
|
||||
ConsoleInfo(String.Format(format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a debug string to the log file.
|
||||
/// </summary>
|
||||
|
|
@ -132,6 +193,16 @@ namespace TShockAPI
|
|||
Write(message, LogLevel.Debug);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a debug string to the log file.
|
||||
/// </summary>
|
||||
/// <param name="format">The format of the message to be written.</param>
|
||||
/// <param name="args">The format arguments.</param>
|
||||
public static void Debug(String format, params String[] args)
|
||||
{
|
||||
Debug(String.Format(format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes objects that are being used.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Streams;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.IO;
|
||||
using System.IO.Streams;
|
||||
using System.Text;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Streams;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.IO;
|
||||
using System.IO.Streams;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.IO;
|
||||
using System.IO.Streams;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Streams;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.ComponentModel;
|
||||
|
|
@ -121,24 +122,24 @@ namespace TShockAPI
|
|||
|
||||
public bool Flush(ServerSock socket)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (socket == null || !socket.active)
|
||||
return false;
|
||||
try
|
||||
{
|
||||
if (socket == null || !socket.active)
|
||||
return false;
|
||||
|
||||
if (buffers[socket.whoAmI].Count < 1)
|
||||
return false;
|
||||
if (buffers[socket.whoAmI].Count < 1)
|
||||
return false;
|
||||
|
||||
byte[] buff = buffers[socket.whoAmI].GetBytes(BytesPerUpdate);
|
||||
if (buff == null)
|
||||
return false;
|
||||
byte[] buff = buffers[socket.whoAmI].GetBytes(BytesPerUpdate);
|
||||
if (buff == null)
|
||||
return false;
|
||||
|
||||
if (SendBytes(socket, buff))
|
||||
{
|
||||
buffers[socket.whoAmI].Pop(buff.Length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (SendBytes(socket, buff))
|
||||
{
|
||||
buffers[socket.whoAmI].Pop(buff.Length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.ConsoleError(e.ToString());
|
||||
|
|
@ -200,7 +201,14 @@ namespace TShockAPI
|
|||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
Log.Warn(e.ToString());
|
||||
switch ((uint)e.ErrorCode)
|
||||
{
|
||||
case 0x80004005:
|
||||
break;
|
||||
default:
|
||||
Log.Warn(e.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
|
|
|||
316
TShockAPI/PaginationTools.cs
Normal file
316
TShockAPI/PaginationTools.cs
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
public static class PaginationTools
|
||||
{
|
||||
public delegate Tuple<string, Color> LineFormatterDelegate(object lineData, int lineIndex, int pageNumber);
|
||||
|
||||
#region [Nested: Settings Class]
|
||||
public class Settings
|
||||
{
|
||||
public bool IncludeHeader { get; set; }
|
||||
|
||||
private string headerFormat;
|
||||
public string HeaderFormat
|
||||
{
|
||||
get { return this.headerFormat; }
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
this.headerFormat = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color HeaderTextColor { get; set; }
|
||||
public bool IncludeFooter { get; set; }
|
||||
|
||||
private string footerFormat;
|
||||
public string FooterFormat
|
||||
{
|
||||
get { return this.footerFormat; }
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
this.footerFormat = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color FooterTextColor { get; set; }
|
||||
public string NothingToDisplayString { get; set; }
|
||||
public LineFormatterDelegate LineFormatter { get; set; }
|
||||
public Color LineTextColor { get; set; }
|
||||
|
||||
private int maxLinesPerPage;
|
||||
|
||||
public int MaxLinesPerPage
|
||||
{
|
||||
get { return this.maxLinesPerPage; }
|
||||
set
|
||||
{
|
||||
if (value <= 0)
|
||||
throw new ArgumentException("The value has to be greater than zero.");
|
||||
|
||||
this.maxLinesPerPage = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int pageLimit;
|
||||
|
||||
public int PageLimit
|
||||
{
|
||||
get { return this.pageLimit; }
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
throw new ArgumentException("The value has to be greater than or equal to zero.");
|
||||
|
||||
this.pageLimit = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Settings()
|
||||
{
|
||||
this.IncludeHeader = true;
|
||||
this.headerFormat = "Page {0} of {1}";
|
||||
this.HeaderTextColor = Color.Green;
|
||||
this.IncludeFooter = true;
|
||||
this.footerFormat = "Type /<command> {0} for more.";
|
||||
this.FooterTextColor = Color.Yellow;
|
||||
this.NothingToDisplayString = null;
|
||||
this.LineFormatter = null;
|
||||
this.LineTextColor = Color.White;
|
||||
this.maxLinesPerPage = 4;
|
||||
this.pageLimit = 0;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static void SendPage(
|
||||
TSPlayer player, int pageNumber, IEnumerable dataToPaginate, int dataToPaginateCount, Settings settings = null)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = new Settings();
|
||||
|
||||
if (dataToPaginateCount == 0)
|
||||
{
|
||||
if (settings.NothingToDisplayString != null)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
player.SendSuccessMessage(settings.NothingToDisplayString);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendMessage(settings.NothingToDisplayString, settings.HeaderTextColor);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int pageCount = ((dataToPaginateCount - 1) / settings.MaxLinesPerPage) + 1;
|
||||
if (settings.PageLimit > 0 && pageCount > settings.PageLimit)
|
||||
pageCount = settings.PageLimit;
|
||||
if (pageNumber > pageCount)
|
||||
pageNumber = pageCount;
|
||||
|
||||
if (settings.IncludeHeader)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
player.SendSuccessMessage(string.Format(settings.HeaderFormat, pageNumber, pageCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendMessage(string.Format(settings.HeaderFormat, pageNumber, pageCount), settings.HeaderTextColor);
|
||||
}
|
||||
}
|
||||
|
||||
int listOffset = (pageNumber - 1) * settings.MaxLinesPerPage;
|
||||
int offsetCounter = 0;
|
||||
int lineCounter = 0;
|
||||
foreach (object lineData in dataToPaginate)
|
||||
{
|
||||
if (lineData == null)
|
||||
continue;
|
||||
if (offsetCounter++ < listOffset)
|
||||
continue;
|
||||
if (lineCounter++ == settings.MaxLinesPerPage)
|
||||
break;
|
||||
|
||||
string lineMessage;
|
||||
Color lineColor = settings.LineTextColor;
|
||||
if (lineData is Tuple<string, Color>)
|
||||
{
|
||||
var lineFormat = (Tuple<string, Color>)lineData;
|
||||
lineMessage = lineFormat.Item1;
|
||||
lineColor = lineFormat.Item2;
|
||||
}
|
||||
else if (settings.LineFormatter != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Tuple<string, Color> lineFormat = settings.LineFormatter(lineData, offsetCounter, pageNumber);
|
||||
if (lineFormat == null)
|
||||
continue;
|
||||
|
||||
lineMessage = lineFormat.Item1;
|
||||
lineColor = lineFormat.Item2;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"The method referenced by LineFormatter has thrown an exception. See inner exception for details.", ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lineMessage = lineData.ToString();
|
||||
}
|
||||
|
||||
if (lineMessage != null)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
Console.WriteLine(lineMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendMessage(lineMessage, lineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lineCounter == 0)
|
||||
{
|
||||
if (settings.NothingToDisplayString != null)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
player.SendSuccessMessage(settings.NothingToDisplayString);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendMessage(settings.NothingToDisplayString, settings.HeaderTextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (settings.IncludeFooter && pageNumber + 1 <= pageCount)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
player.SendInfoMessage(string.Format(settings.FooterFormat, pageNumber + 1, pageNumber, pageCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendMessage(string.Format(settings.FooterFormat, pageNumber + 1, pageNumber, pageCount), settings.FooterTextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendPage(TSPlayer player, int pageNumber, IList dataToPaginate, Settings settings = null)
|
||||
{
|
||||
PaginationTools.SendPage(player, pageNumber, dataToPaginate, dataToPaginate.Count, settings);
|
||||
}
|
||||
|
||||
public static List<string> BuildLinesFromTerms(
|
||||
IEnumerable terms, Func<object, string> termFormatter = null, string separator = ", ", int maxCharsPerLine = 80)
|
||||
{
|
||||
List<string> lines = new List<string>();
|
||||
StringBuilder lineBuilder = new StringBuilder();
|
||||
foreach (object term in terms)
|
||||
{
|
||||
if (term == null && termFormatter == null)
|
||||
continue;
|
||||
|
||||
string termString;
|
||||
if (termFormatter != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
termString = termFormatter(term);
|
||||
|
||||
if (termString == null)
|
||||
continue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"The method represented by termFormatter has thrown an exception. See inner exception for details.", ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
termString = term.ToString();
|
||||
}
|
||||
|
||||
bool goesOnNextLine = (lineBuilder.Length + termString.Length > maxCharsPerLine);
|
||||
if (!goesOnNextLine)
|
||||
{
|
||||
if (lineBuilder.Length > 0)
|
||||
lineBuilder.Append(separator);
|
||||
lineBuilder.Append(termString);
|
||||
}
|
||||
else
|
||||
{
|
||||
// A separator should always be at the end of a line as we know it is followed by another line.
|
||||
lineBuilder.Append(separator);
|
||||
lines.Add(lineBuilder.ToString());
|
||||
lineBuilder.Clear();
|
||||
|
||||
lineBuilder.Append(termString);
|
||||
}
|
||||
}
|
||||
if (lineBuilder.Length > 0)
|
||||
lines.Add(lineBuilder.ToString());
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
public static bool TryParsePageNumber(
|
||||
List<string> commandParameters, int expectedParamterIndex, TSPlayer errorMessageReceiver, out int pageNumber)
|
||||
{
|
||||
pageNumber = 1;
|
||||
if (commandParameters.Count <= expectedParamterIndex)
|
||||
return true;
|
||||
|
||||
string pageNumberRaw = commandParameters[expectedParamterIndex];
|
||||
if (!int.TryParse(pageNumberRaw, out pageNumber) || pageNumber < 1)
|
||||
{
|
||||
if (errorMessageReceiver != null)
|
||||
errorMessageReceiver.SendErrorMessage(string.Format("\"{0}\" is not a valid page number.", pageNumberRaw));
|
||||
|
||||
pageNumber = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.ComponentModel;
|
||||
|
|
@ -26,161 +27,258 @@ namespace TShockAPI
|
|||
{
|
||||
public static class Permissions
|
||||
{
|
||||
//Permissions with blank descriptions basically means its described by the commands it gives access to.
|
||||
// tshock.account nodes
|
||||
|
||||
[Description("Allows player to get user info")] public static readonly string userinfo;
|
||||
[Description("User can register account in game")]
|
||||
public static readonly string canregister = "tshock.account.register";
|
||||
|
||||
[Description("")] public static readonly string causeevents;
|
||||
[Description("User can login in game")]
|
||||
public static readonly string canlogin = "tshock.account.login";
|
||||
|
||||
[Description("Required to be able to build (modify tiles and liquid)")] public static readonly string canbuild;
|
||||
[Description("User can change password in game")]
|
||||
public static readonly string canchangepassword = "tshock.account.changepassword";
|
||||
|
||||
[Description("")] public static readonly string kill;
|
||||
// tshock.admin nodes
|
||||
|
||||
[Description("Allows you to use banned items")] public static readonly string usebanneditem;
|
||||
[Description("Prevents you from being kicked.")]
|
||||
public static readonly string immunetokick = "tshock.admin.nokick";
|
||||
|
||||
[Description("Allows you to edit the spawn")] public static readonly string editspawn;
|
||||
[Description("Prevents you from being banned.")]
|
||||
public static readonly string immunetoban = "tshock.admin.noban";
|
||||
|
||||
[Description("Prevents you from being kicked")] public static readonly string immunetokick;
|
||||
[Description("Specific log messages are sent to users with this permission.")]
|
||||
public static readonly string logs = "tshock.admin.viewlogs";
|
||||
|
||||
[Description("Prevents you from being banned")] public static readonly string immunetoban;
|
||||
[Description("User can kick others.")]
|
||||
public static readonly string kick = "tshock.admin.kick";
|
||||
|
||||
[Description("Prevents you from being reverted by kill tile abuse detection")] public static readonly string
|
||||
ignorekilltiledetection;
|
||||
[Description("User can ban others.")]
|
||||
public static readonly string ban = "tshock.admin.ban";
|
||||
|
||||
[Description("Prevents you from being reverted by place tile abuse detection")] public static readonly string
|
||||
ignoreplacetiledetection;
|
||||
[Description("User can manage warps.")]
|
||||
public static readonly string managewarp = "tshock.admin.warp";
|
||||
|
||||
[Description("Prevents you from being disabled by liquid set abuse detection")] public static readonly string
|
||||
ignoreliquidsetdetection;
|
||||
[Description("User can manage item bans.")]
|
||||
public static readonly string manageitem = "tshock.admin.itemban";
|
||||
|
||||
[Description("Prevents you from being disabled by liquid set abuse detection")] public static readonly string
|
||||
ignoreprojectiledetection;
|
||||
[Description("User can manage groups.")]
|
||||
public static readonly string managegroup = "tshock.admin.group";
|
||||
|
||||
[Description("Prevents you from being reverted by no clip detection")] public static readonly string
|
||||
ignorenoclipdetection;
|
||||
[Description("User can manage regions.")]
|
||||
public static readonly string manageregion = "tshock.admin.region";
|
||||
|
||||
[Description("Prevents you from being disabled by stack hack detection")] public static readonly string
|
||||
ignorestackhackdetection;
|
||||
[Description("User can mute and unmute users")]
|
||||
public static readonly string mute = "tshock.admin.mute";
|
||||
|
||||
[Description("Prevents you from being kicked by hacked health detection")] public static readonly string
|
||||
ignorestathackdetection;
|
||||
[Description("User can see the id of players with /who")]
|
||||
public static readonly string seeids = "tshock.admin.seeplayerids";
|
||||
|
||||
[Description("Prevents your actions from being ignored if damage is too high")] public static readonly string
|
||||
ignoredamagecap;
|
||||
[Description("User can save all the players SSI state.")]
|
||||
public static readonly string savessi = "tshock.admin.savessi";
|
||||
|
||||
[Description("Specific log messages are sent to users with this permission")] public static readonly string logs;
|
||||
[Description("User can elevate other users' groups temporarily.")]
|
||||
public static readonly string settempgroup = "tshock.admin.tempgroup";
|
||||
|
||||
[Description("Allows you to bypass the max slots for up to 5 slots above your max")] public static readonly string
|
||||
reservedslot;
|
||||
[Description("User can broadcast messages.")]
|
||||
public static readonly string broadcast = "tshock.admin.broadcast";
|
||||
|
||||
[Description("User is notified when an update is available")] public static readonly string maintenance;
|
||||
[Description("User can get other users' info.")]
|
||||
public static readonly string userinfo = "tshock.admin.userinfo";
|
||||
|
||||
[Description("User can kick others")] public static readonly string kick;
|
||||
// tshock.buff nodes
|
||||
|
||||
[Description("User can ban others")] public static readonly string ban;
|
||||
[Description("User can buff self.")]
|
||||
public static readonly string buff = "tshock.buff.self";
|
||||
|
||||
[Description("User can modify the whitelist")] public static readonly string whitelist;
|
||||
[Description("User can buff other players.")]
|
||||
public static readonly string buffplayer = "tshock.buff.others";
|
||||
|
||||
[Description("User can spawn bosses")] public static readonly string spawnboss;
|
||||
// tshock.cfg nodes
|
||||
|
||||
[Description("User can spawn npcs")] public static readonly string spawnmob;
|
||||
[Description("User is notified when an update is available, user can turn off / restart the server.")]
|
||||
public static readonly string maintenance = "tshock.cfg.maintenance";
|
||||
|
||||
[Description("User can teleport")] public static readonly string tp;
|
||||
[Description("User can modify the whitelist.")]
|
||||
public static readonly string whitelist = "tshock.cfg.whitelist";
|
||||
|
||||
[Description("User can teleport people to them")] public static readonly string tphere;
|
||||
[Description("User can edit the server password.")]
|
||||
public static readonly string cfgpassword = "tshock.cfg.password";
|
||||
|
||||
[Description("User can use warps")] public static readonly string warp;
|
||||
[Description("User can reload the configurations file.")]
|
||||
public static readonly string cfgreload = "tshock.cfg.reload";
|
||||
|
||||
[Description("User can manage warps")] public static readonly string managewarp;
|
||||
[Description("User can edit the max spawns.")]
|
||||
public static readonly string cfgmaxspawns = "tshock.cfg.maxspawns";
|
||||
|
||||
[Description("User can manage item bans")] public static readonly string manageitem;
|
||||
[Description("User can edit the spawnrate.")]
|
||||
public static readonly string cfgspawnrate = "tshock.cfg.spawnrate";
|
||||
|
||||
[Description("User can manage groups")] public static readonly string managegroup;
|
||||
[Description("User can download updates to plugins that are currently running.")]
|
||||
public static readonly string updateplugins = "tshock.cfg.updateplugins";
|
||||
|
||||
[Description("User can edit sevrer configurations")] public static readonly string cfg;
|
||||
// tshock.ignore nodes
|
||||
|
||||
[Description("")] public static readonly string time;
|
||||
[Description("Prevents you from being reverted by kill tile abuse detection.")]
|
||||
public static readonly string ignorekilltiledetection = "tshock.ignore.removetile";
|
||||
|
||||
[Description("")] public static readonly string pvpfun;
|
||||
[Description("Prevents you from being reverted by place tile abuse detection.")]
|
||||
public static readonly string ignoreplacetiledetection = "tshock.ignore.placetile";
|
||||
|
||||
[Description("User can edit regions")] public static readonly string manageregion;
|
||||
[Description("Prevents you from being disabled by liquid set abuse detection.")]
|
||||
public static readonly string ignoreliquidsetdetection = "tshock.ignore.liquid";
|
||||
|
||||
[Description("Meant for super admins only")] public static readonly string rootonly;
|
||||
[Description("Prevents you from being disabled by projectile abuse detection.")]
|
||||
public static readonly string ignoreprojectiledetection = "tshock.ignore.projectile";
|
||||
|
||||
[Description("User can whisper to others")] public static readonly string whisper;
|
||||
[Description("Prevents you from being reverted by no clip detection.")]
|
||||
public static readonly string ignorenoclipdetection = "tshock.ignore.noclip";
|
||||
|
||||
[Description("")] public static readonly string annoy;
|
||||
[Description("Prevents you from being disabled by stack hack detection.")]
|
||||
public static readonly string ignorestackhackdetection = "tshock.ignore.itemstack";
|
||||
|
||||
[Description("User can kill all enemy npcs")] public static readonly string butcher;
|
||||
[Description("Prevents you from being kicked by hacked health detection.")]
|
||||
public static readonly string ignorestathackdetection = "tshock.ignore.stats";
|
||||
|
||||
[Description("User can spawn items")] public static readonly string item;
|
||||
[Description("Prevents your actions from being ignored if damage is too high.")]
|
||||
public static readonly string ignoredamagecap = "tshock.ignore.damage";
|
||||
|
||||
[Description("User can clear item drops.")] public static readonly string clearitems;
|
||||
[Description("Bypass server side inventory checks")]
|
||||
public static readonly string bypassinventorychecks = "tshock.ignore.ssi";
|
||||
|
||||
[Description("")] public static readonly string heal;
|
||||
[Description("Allow unrestricted SendTileSquare usage, for client side world editing.")]
|
||||
public static readonly string allowclientsideworldedit = "tshock.ignore.sendtilesquare";
|
||||
|
||||
[Description("User can buff self")] public static readonly string buff;
|
||||
// tshock.item nodes
|
||||
|
||||
[Description("User can buff other players")] public static readonly string buffplayer;
|
||||
[Description("User can spawn items.")]
|
||||
public static readonly string item = "tshock.item.spawn";
|
||||
|
||||
[Description("")] public static readonly string grow;
|
||||
[Description("User can clear items.")]
|
||||
public static readonly string clearitems = "tshock.item.clear";
|
||||
|
||||
[Description("User can change hardmode state.")] public static readonly string hardmode;
|
||||
[Description("Allows you to use banned items.")]
|
||||
public static readonly string usebanneditem = "tshock.item.usebanned";
|
||||
|
||||
[Description("User can change the homes of NPCs.")] public static readonly string movenpc;
|
||||
// tshock.npc nodes
|
||||
|
||||
[Description("Users can stop people from teleporting to them")] public static readonly string tpallow;
|
||||
[Description("User can spawn bosses.")]
|
||||
public static readonly string spawnboss = "tshock.npc.spawnboss";
|
||||
|
||||
[Description("Users can tp to anyone")] public static readonly string tpall;
|
||||
[Description("User can spawn npcs.")]
|
||||
public static readonly string spawnmob = "tshock.npc.spawnmob";
|
||||
|
||||
[Description("Users can tp to people without showing a notice")] public static readonly string tphide;
|
||||
[Description("User can kill all enemy npcs.")]
|
||||
public static readonly string butcher = "tshock.npc.butcher";
|
||||
|
||||
[Description("User can convert hallow into corruption and vice-versa")] public static readonly string converthardmode;
|
||||
[Description("User can summon bosses using items")]
|
||||
public static readonly string summonboss = "tshock.npc.summonboss";
|
||||
|
||||
[Description("User can mute and unmute users")] public static readonly string mute;
|
||||
[Description("User can start invasions (Goblin/Snow Legion) using items")]
|
||||
public static readonly string startinvasion = "tshock.npc.startinvasion";
|
||||
|
||||
[Description("User can register account in game")] public static readonly string canregister;
|
||||
// tshock.superadmin nodes
|
||||
|
||||
[Description("User can login in game")] public static readonly string canlogin;
|
||||
[Description("Meant for super admins only.")]
|
||||
public static readonly string authverify = "tshock.superadmin.authverify";
|
||||
|
||||
[Description("User can change password in game")] public static readonly string canchangepassword;
|
||||
[Description("Meant for super admins only.")]
|
||||
public static readonly string user = "tshock.superadmin.user";
|
||||
|
||||
[Description("User can use party chat in game")] public static readonly string canpartychat;
|
||||
// tshock.tp nodes
|
||||
|
||||
[Description("User can talk in third person")] public static readonly string cantalkinthird;
|
||||
[Description("User can teleport to others.")]
|
||||
public static readonly string tp = "tshock.tp.self";
|
||||
|
||||
[Description("Bypass server side inventory checks")] public static readonly string bypassinventorychecks;
|
||||
[Description("User can teleport people to them.")]
|
||||
public static readonly string tphere = "tshock.tp.others";
|
||||
|
||||
[Description("Allow unrestricted SendTileSquare usage, for client side world editing.")] public static readonly
|
||||
string allowclientsideworldedit;
|
||||
[Description("Users can stop people from teleporting to them")]
|
||||
public static readonly string tpallow = "tshock.tp.block";
|
||||
|
||||
[Description("User can summon bosses using items")]
|
||||
public static readonly string summonboss;
|
||||
[Description("Users can tp to anyone")]
|
||||
public static readonly string tpall = "tshock.tp.toall";
|
||||
|
||||
[Description("User can start invasions (Goblin/Snow Legion) using items")]
|
||||
public static readonly string startinvasion;
|
||||
[Description("Users can tp to people without showing a notice")]
|
||||
public static readonly string tphide = "tshock.tp.silent";
|
||||
|
||||
[Description("User can see the id of players with /who")]
|
||||
public static readonly string seeids;
|
||||
[Description("User can use /home.")]
|
||||
public static readonly string home = "tshock.tp.home";
|
||||
|
||||
[Description("User can save all the players SSI state.")]
|
||||
public static readonly string savessi;
|
||||
[Description("User can use /spawn.")]
|
||||
public static readonly string spawn = "tshock.tp.spawn";
|
||||
|
||||
[Description("User can use rest api calls.")]
|
||||
public static readonly string restapi;
|
||||
// tshock.world nodes
|
||||
|
||||
[Description("User can force the server to Christmas mode.")] public static readonly string xmas;
|
||||
[Description("Allows you to edit the spawn.")]
|
||||
public static readonly string editspawn = "tshock.world.editspawn";
|
||||
|
||||
static Permissions()
|
||||
{
|
||||
foreach (var field in typeof (Permissions).GetFields())
|
||||
{
|
||||
field.SetValue(null, field.Name);
|
||||
}
|
||||
[Description("User can set the time.")]
|
||||
public static readonly string time = "tshock.world.settime";
|
||||
|
||||
//Backwards compatability.
|
||||
restapi = "api";
|
||||
}
|
||||
[Description("User can grow plants.")]
|
||||
public static readonly string grow = "tshock.world.grow";
|
||||
|
||||
[Description("User can change hardmode state.")]
|
||||
public static readonly string hardmode = "tshock.world.hardmode";
|
||||
|
||||
[Description("User can change the homes of NPCs.")]
|
||||
public static readonly string movenpc = "tshock.world.movenpc";
|
||||
|
||||
[Description("User can convert hallow into corruption and vice-versa")]
|
||||
public static readonly string converthardmode = "tshock.world.converthardmode";
|
||||
|
||||
[Description("User can force the server to Christmas mode.")]
|
||||
public static readonly string xmas = "tshock.world.setxmas";
|
||||
|
||||
[Description("User can save the world.")]
|
||||
public static readonly string worldsave = "tshock.world.save";
|
||||
|
||||
[Description("User can settle liquids.")]
|
||||
public static readonly string worldsettle = "tshock.world.settleliquids";
|
||||
|
||||
[Description("User can get the world info.")]
|
||||
public static readonly string worldinfo = "tshock.world.info";
|
||||
|
||||
[Description("User can set the world spawn.")]
|
||||
public static readonly string worldspawn = "tshock.world.setspawn";
|
||||
|
||||
[Description("User can cause some events.")]
|
||||
public static readonly string causeevents = "tshock.world.causeevents";
|
||||
|
||||
[Description("User can modify the world.")]
|
||||
public static readonly string canbuild = "tshock.world.modify";
|
||||
|
||||
// Non-grouped
|
||||
|
||||
[Description("User can kill others.")]
|
||||
public static readonly string kill = "tshock.kill";
|
||||
|
||||
[Description("Allows you to bypass the max slots for up to 5 slots above your max.")]
|
||||
public static readonly string reservedslot = "tshock.reservedslot";
|
||||
|
||||
[Description("User can use warps.")]
|
||||
public static readonly string warp = "tshock.warp";
|
||||
|
||||
[Description("User can slap others.")]
|
||||
public static readonly string slap = "tshock.slap";
|
||||
|
||||
[Description("User can whisper to others.")]
|
||||
public static readonly string whisper = "tshock.whisper";
|
||||
|
||||
[Description("User can annoy others.")]
|
||||
public static readonly string annoy = "tshock.annoy";
|
||||
|
||||
[Description("User can heal players.")]
|
||||
public static readonly string heal = "tshock.heal";
|
||||
|
||||
[Description("User can use party chat in game")]
|
||||
public static readonly string canpartychat = "tshock.partychat";
|
||||
|
||||
[Description("User can talk in third person")]
|
||||
public static readonly string cantalkinthird = "tshock.thirdperson";
|
||||
|
||||
[Description("User can get the server info.")]
|
||||
public static readonly string serverinfo = "tshock.info";
|
||||
|
||||
/// <summary>
|
||||
/// Lists all commands associated with a given permission
|
||||
|
|
@ -191,7 +289,7 @@ namespace TShockAPI
|
|||
{
|
||||
if (Commands.ChatCommands.Count < 1)
|
||||
Commands.InitCommands();
|
||||
return Commands.ChatCommands.Where(c => c.Permission == perm).ToList();
|
||||
return Commands.ChatCommands.Where(c => c.Permissions.Contains(perm)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
87
TShockAPI/PluginUpdater/PluginUpdaterThread.cs
Normal file
87
TShockAPI/PluginUpdater/PluginUpdaterThread.cs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Terraria;
|
||||
|
||||
namespace TShockAPI.PluginUpdater
|
||||
{
|
||||
class PluginUpdaterThread
|
||||
{
|
||||
private TSPlayer invoker;
|
||||
public PluginUpdaterThread(TSPlayer player)
|
||||
{
|
||||
invoker = player;
|
||||
PluginVersionCheck.PluginUpdate += PluginUpdate;
|
||||
HandleUpdate();
|
||||
}
|
||||
|
||||
private void HandleUpdate()
|
||||
{
|
||||
foreach(PluginContainer cont in ProgramServer.Plugins)
|
||||
new Thread(PluginVersionCheck.CheckPlugin).Start(cont.Plugin);
|
||||
}
|
||||
|
||||
private int Updates = 0;
|
||||
private void PluginUpdate(UpdateArgs args)
|
||||
{
|
||||
Updates++;
|
||||
if(args.Success && String.IsNullOrEmpty(args.Error))
|
||||
{
|
||||
invoker.SendSuccessMessage(String.Format("{0} was downloaded successfully.", args.Plugin.Name));
|
||||
}
|
||||
else if(args.Success)
|
||||
{
|
||||
invoker.SendSuccessMessage(String.Format("{0} was skipped. Reason: {1}", args.Plugin.Name, args.Error));
|
||||
}
|
||||
else
|
||||
{
|
||||
invoker.SendSuccessMessage(String.Format("{0} failed to downloaded. Error: {1}", args.Plugin.Name, args.Error));
|
||||
}
|
||||
|
||||
if(Updates >= Terraria.ProgramServer.Plugins.Count)
|
||||
{
|
||||
PluginVersionCheck.PluginUpdate -= PluginUpdate;
|
||||
|
||||
invoker.SendSuccessMessage("All plugins have been downloaded. Now copying them to the plugin folder...");
|
||||
|
||||
string folder = Path.Combine(TShock.SavePath, "UpdatedPlugins");
|
||||
string dest = Path.Combine(TShock.SavePath, "..", "ServerPlugins");
|
||||
|
||||
foreach (string dir in Directory.GetDirectories(folder, "*", System.IO.SearchOption.AllDirectories))
|
||||
{
|
||||
string new_folder = dest + dir.Substring(folder.Length);
|
||||
if (!Directory.Exists(new_folder))
|
||||
Directory.CreateDirectory(new_folder);
|
||||
}
|
||||
|
||||
foreach (string file_name in Directory.GetFiles(folder, "*.*", System.IO.SearchOption.AllDirectories))
|
||||
{
|
||||
TSPlayer.Server.SendSuccessMessage(String.Format("Copied {0}", file_name));
|
||||
File.Copy(file_name, dest + file_name.Substring(folder.Length), true);
|
||||
}
|
||||
|
||||
|
||||
Directory.Delete(folder, true);
|
||||
|
||||
invoker.SendSuccessMessage("All plugins have been processed. Restart the server to have access to the new plugins.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
127
TShockAPI/PluginUpdater/PluginVersionCheck.cs
Normal file
127
TShockAPI/PluginUpdater/PluginVersionCheck.cs
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using JsonLoader;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace TShockAPI.PluginUpdater
|
||||
{
|
||||
public class PluginVersionCheck
|
||||
{
|
||||
public delegate void PluginUpdateD(UpdateArgs e);
|
||||
public static event PluginUpdateD PluginUpdate;
|
||||
public static void OnPluginUpdate(UpdateArgs args)
|
||||
{
|
||||
if (PluginUpdate == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PluginUpdate(args);
|
||||
}
|
||||
|
||||
public static void CheckPlugin(object p)
|
||||
{
|
||||
TerrariaPlugin plugin = (TerrariaPlugin)p;
|
||||
UpdateArgs args = new UpdateArgs {Plugin = plugin, Success = true, Error = ""};
|
||||
List<string> files = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
if (!String.IsNullOrEmpty(plugin.UpdateURL))
|
||||
{
|
||||
var request = HttpWebRequest.Create(plugin.UpdateURL);
|
||||
VersionInfo vi;
|
||||
|
||||
request.Timeout = 5000;
|
||||
using (var response = request.GetResponse())
|
||||
{
|
||||
using (var reader = new StreamReader(response.GetResponseStream()))
|
||||
{
|
||||
vi = JsonConvert.DeserializeObject<VersionInfo>(reader.ReadToEnd());
|
||||
}
|
||||
}
|
||||
|
||||
System.Version v = System.Version.Parse((vi.version.ToString()));
|
||||
|
||||
if (!v.Equals(plugin.Version))
|
||||
{
|
||||
DownloadPackage pkg;
|
||||
request = HttpWebRequest.Create(vi.url);
|
||||
|
||||
request.Timeout = 5000;
|
||||
using (var response = request.GetResponse())
|
||||
{
|
||||
using (var reader = new StreamReader(response.GetResponseStream()))
|
||||
{
|
||||
pkg = JsonConvert.DeserializeObject<DownloadPackage>(reader.ReadToEnd());
|
||||
}
|
||||
}
|
||||
|
||||
foreach (PluginFile f in pkg.files)
|
||||
{
|
||||
using (WebClient Client = new WebClient())
|
||||
{
|
||||
string dir = Path.Combine(TShock.SavePath, "UpdatedPlugins");
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
Client.DownloadFile(f.url,
|
||||
Path.Combine(dir, f.destination));
|
||||
|
||||
files.Add(Path.Combine(dir, f.destination));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Error = "Plugin is up to date.";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Error = "Plugin has no updater recorded.";
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
args.Success = false;
|
||||
args.Error = e.Message;
|
||||
if(files.Count > 0)
|
||||
{
|
||||
foreach(string s in files)
|
||||
{
|
||||
File.Delete(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OnPluginUpdate(args);
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateArgs
|
||||
{
|
||||
public TerrariaPlugin Plugin { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Error { get; set; }
|
||||
}
|
||||
}
|
||||
87
TShockAPI/PluginUpdater/VersionInfo.cs
Normal file
87
TShockAPI/PluginUpdater/VersionInfo.cs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace JsonLoader
|
||||
{
|
||||
class VersionInfo
|
||||
{
|
||||
public Version version;
|
||||
public string url;
|
||||
}
|
||||
|
||||
public class Version
|
||||
{
|
||||
public int Major;
|
||||
public int Minor;
|
||||
public int Build;
|
||||
public int Revision;
|
||||
public int MajorRevision;
|
||||
public int MinorRevision;
|
||||
|
||||
public Version()
|
||||
{
|
||||
SetVersion(0,0,0,0);
|
||||
}
|
||||
|
||||
public Version(int m)
|
||||
{
|
||||
SetVersion(m, 0, 0, 0);
|
||||
}
|
||||
|
||||
public Version(int ma, int mi)
|
||||
{
|
||||
SetVersion(ma, mi, 0, 0);
|
||||
}
|
||||
|
||||
public Version(int ma, int mi, int b)
|
||||
{
|
||||
SetVersion(ma, mi, b, 0);
|
||||
}
|
||||
|
||||
public Version(int ma, int mi, int b, int r)
|
||||
{
|
||||
SetVersion(ma, mi, b, r);
|
||||
}
|
||||
|
||||
private void SetVersion(int ma, int mi, int b, int r)
|
||||
{
|
||||
Major = ma;
|
||||
Minor = mi;
|
||||
Build = b;
|
||||
Revision = r;
|
||||
}
|
||||
|
||||
public string ToString()
|
||||
{
|
||||
return String.Format("{0}.{1}.{2}.{3}", Major, Minor, Build, Revision);
|
||||
}
|
||||
}
|
||||
|
||||
class DownloadPackage
|
||||
{
|
||||
public List<PluginFile> files;
|
||||
}
|
||||
|
||||
class PluginFile
|
||||
{
|
||||
public string url;
|
||||
public string destination = "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
|
@ -25,9 +26,9 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTitle("TShock for Terraria")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Nyx Team")]
|
||||
[assembly: AssemblyCompany("Nyx Studios & TShock Contributors")]
|
||||
[assembly: AssemblyProduct("TShockAPI")]
|
||||
[assembly: AssemblyCopyright("Copyright © Nyx Team 2012")]
|
||||
[assembly: AssemblyCopyright("Copyright © Nyx Studios 2011-2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
|
@ -48,5 +49,5 @@ using System.Runtime.InteropServices;
|
|||
// Build Number
|
||||
// MMdd of the build
|
||||
|
||||
[assembly: AssemblyVersion("4.0.0.0923")]
|
||||
[assembly: AssemblyFileVersion("4.0.0.0923")]
|
||||
[assembly: AssemblyVersion("4.1.0.0926")]
|
||||
[assembly: AssemblyFileVersion("4.1.0.0926")]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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;
|
||||
|
|
|
|||
5
TShockAPI/Resources.Designer.cs
generated
5
TShockAPI/Resources.Designer.cs
generated
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -27,9 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TShockAPI {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.ComponentModel;
|
||||
|
|
@ -38,6 +39,15 @@ namespace Rests
|
|||
/// <returns>Response object or null to not handle request</returns>
|
||||
public delegate object RestCommandD(RestVerbs verbs, IParameterCollection parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Secure Rest command delegate including token data.
|
||||
/// </summary>
|
||||
/// <param name="parameters">Parameters in the url</param>
|
||||
/// <param name="verbs">{x} in urltemplate</param>
|
||||
/// <param name="tokenData">The data of stored for the provided token.</param>
|
||||
/// <returns>Response object or null to not handle request</returns>
|
||||
public delegate object SecureRestCommandD(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData);
|
||||
|
||||
public class Rest : IDisposable
|
||||
{
|
||||
private readonly List<RestCommand> commands = new List<RestCommand>();
|
||||
|
|
@ -170,24 +180,47 @@ namespace Rests
|
|||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
return new RestObject("500")
|
||||
{
|
||||
{"status", "500"},
|
||||
{"error", "Internal server error."},
|
||||
{"errormsg", exception.Message},
|
||||
{"stacktrace", exception.StackTrace},
|
||||
};
|
||||
}
|
||||
return new Dictionary<string, string>
|
||||
return new RestObject("404")
|
||||
{
|
||||
{"status", "404"},
|
||||
{"error", "Specified API endpoint doesn't exist. Refer to the documentation for a list of valid endpoints."}
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
||||
{
|
||||
return cmd.Callback(verbs, parms);
|
||||
object result = cmd.Execute(verbs, parms);
|
||||
if (cmd.DoLog)
|
||||
Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual string BuildRequestUri(
|
||||
RestCommand cmd, RestVerbs verbs, IParameterCollection parms, bool includeToken = true
|
||||
) {
|
||||
StringBuilder requestBuilder = new StringBuilder(cmd.UriTemplate);
|
||||
char separator = '?';
|
||||
foreach (IParameter paramImpl in parms)
|
||||
{
|
||||
Parameter param = (paramImpl as Parameter);
|
||||
if (param == null || (!includeToken && param.Name.Equals("token", StringComparison.InvariantCultureIgnoreCase)))
|
||||
continue;
|
||||
|
||||
requestBuilder.Append(separator);
|
||||
requestBuilder.Append(param.Name);
|
||||
requestBuilder.Append('=');
|
||||
requestBuilder.Append(param.Value);
|
||||
separator = '&';
|
||||
}
|
||||
|
||||
return requestBuilder.ToString();
|
||||
}
|
||||
|
||||
#region Dispose
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,8 +15,10 @@ 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.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using HttpServer;
|
||||
|
||||
namespace Rests
|
||||
{
|
||||
|
|
@ -26,8 +28,10 @@ namespace Rests
|
|||
public string UriTemplate { get; protected set; }
|
||||
public string UriVerbMatch { get; protected set; }
|
||||
public string[] UriVerbs { get; protected set; }
|
||||
public RestCommandD Callback { get; protected set; }
|
||||
public bool RequiresToken { get; set; }
|
||||
public virtual bool RequiresToken { get { return false; } }
|
||||
public bool DoLog { get; set; }
|
||||
|
||||
private RestCommandD callback;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
|
@ -42,8 +46,8 @@ namespace Rests
|
|||
UriVerbMatch = string.Format("^{0}$", string.Join("([^/]*)", Regex.Split(uritemplate, "\\{[^\\{\\}]*\\}")));
|
||||
var matches = Regex.Matches(uritemplate, "\\{([^\\{\\}]*)\\}");
|
||||
UriVerbs = (from Match match in matches select match.Groups[1].Value).ToArray();
|
||||
Callback = callback;
|
||||
RequiresToken = true;
|
||||
this.callback = callback;
|
||||
DoLog = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -60,5 +64,43 @@ namespace Rests
|
|||
{
|
||||
get { return UriVerbs.Length > 0; }
|
||||
}
|
||||
|
||||
public virtual object Execute(RestVerbs verbs, IParameterCollection parameters)
|
||||
{
|
||||
return callback(verbs, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
public class SecureRestCommand: RestCommand
|
||||
{
|
||||
public override bool RequiresToken { get { return true; } }
|
||||
public string[] Permissions { get; set; }
|
||||
|
||||
private SecureRestCommandD callback;
|
||||
|
||||
public SecureRestCommand(string name, string uritemplate, SecureRestCommandD callback, params string[] permissions)
|
||||
: base(name, uritemplate, null)
|
||||
{
|
||||
this.callback = callback;
|
||||
Permissions = permissions;
|
||||
}
|
||||
|
||||
public SecureRestCommand(string uritemplate, SecureRestCommandD callback, params string[] permissions)
|
||||
: this(string.Empty, uritemplate, callback, permissions)
|
||||
{
|
||||
}
|
||||
|
||||
public override object Execute(RestVerbs verbs, IParameterCollection parameters)
|
||||
{
|
||||
return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." };
|
||||
}
|
||||
|
||||
public object Execute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (tokenData.Equals(SecureRest.TokenData.None))
|
||||
return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." };
|
||||
|
||||
return callback(verbs, parameters, tokenData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,9 +15,11 @@ 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;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using HttpServer;
|
||||
using Rests;
|
||||
|
|
@ -38,78 +40,140 @@ namespace TShockAPI
|
|||
public void RegisterRestfulCommands()
|
||||
{
|
||||
// Server Commands
|
||||
Rest.Register(new RestCommand("/v2/server/broadcast", ServerBroadcast));
|
||||
Rest.Register(new RestCommand("/v2/server/off", ServerOff));
|
||||
Rest.Register(new RestCommand("/v2/server/rawcmd", ServerCommand));
|
||||
Rest.Register(new RestCommand("/v2/server/status", ServerStatusV2) { RequiresToken = false });
|
||||
Rest.Register(new RestCommand("/tokentest", ServerTokenTest));
|
||||
Rest.Register(new RestCommand("/status", ServerStatus) { RequiresToken = false });
|
||||
if (TShock.Config.EnableTokenEndpointAuthentication)
|
||||
{
|
||||
Rest.Register(new SecureRestCommand("/v2/server/status", ServerStatusV2));
|
||||
Rest.Register(new SecureRestCommand("/status", ServerStatus));
|
||||
Rest.Register(new SecureRestCommand("/v3/server/motd", ServerMotd));
|
||||
Rest.Register(new SecureRestCommand("/v3/server/rules", ServerRules));
|
||||
}
|
||||
else
|
||||
{
|
||||
Rest.Register(new RestCommand("/v2/server/status", (a, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None)));
|
||||
Rest.Register(new RestCommand("/status", (a, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None)));
|
||||
Rest.Register(new RestCommand("/v3/server/motd", (a, b) => this.ServerMotd(a, b, SecureRest.TokenData.None)));
|
||||
Rest.Register(new RestCommand("/v3/server/rules", (a, b) => this.ServerRules(a, b, SecureRest.TokenData.None)));
|
||||
}
|
||||
|
||||
Rest.Register(new SecureRestCommand("/v2/server/broadcast", ServerBroadcast));
|
||||
Rest.Register(new SecureRestCommand("/v3/server/reload", ServerReload, RestPermissions.restcfg));
|
||||
Rest.Register(new SecureRestCommand("/v2/server/off", ServerOff, RestPermissions.restmaintenance));
|
||||
Rest.Register(new SecureRestCommand("/v3/server/restart", ServerRestart, RestPermissions.restmaintenance));
|
||||
Rest.Register(new SecureRestCommand("/v2/server/rawcmd", ServerCommand, RestPermissions.restrawcommand));
|
||||
Rest.Register(new SecureRestCommand("/v3/server/rawcmd", ServerCommandV3, RestPermissions.restrawcommand));
|
||||
Rest.Register(new SecureRestCommand("/tokentest", ServerTokenTest));
|
||||
|
||||
// User Commands
|
||||
Rest.Register(new RestCommand("/v2/users/activelist", UserActiveListV2));
|
||||
Rest.Register(new RestCommand("/v2/users/create", UserCreateV2));
|
||||
Rest.Register(new RestCommand("/v2/users/list", UserListV2));
|
||||
Rest.Register(new RestCommand("/v2/users/read", UserInfoV2));
|
||||
Rest.Register(new RestCommand("/v2/users/destroy", UserDestroyV2));
|
||||
Rest.Register(new RestCommand("/v2/users/update", UserUpdateV2));
|
||||
Rest.Register(new SecureRestCommand("/v2/users/activelist", UserActiveListV2, RestPermissions.restviewusers));
|
||||
Rest.Register(new SecureRestCommand("/v2/users/create", UserCreateV2, RestPermissions.restmanageusers) { DoLog = false });
|
||||
Rest.Register(new SecureRestCommand("/v2/users/list", UserListV2, RestPermissions.restviewusers));
|
||||
Rest.Register(new SecureRestCommand("/v2/users/read", UserInfoV2, RestPermissions.restviewusers));
|
||||
Rest.Register(new SecureRestCommand("/v2/users/destroy", UserDestroyV2, RestPermissions.restmanageusers));
|
||||
Rest.Register(new SecureRestCommand("/v2/users/update", UserUpdateV2, RestPermissions.restmanageusers) { DoLog = false });
|
||||
|
||||
// Ban Commands
|
||||
Rest.Register(new RestCommand("/bans/create", BanCreate));
|
||||
Rest.Register(new RestCommand("/v2/bans/list", BanListV2));
|
||||
Rest.Register(new RestCommand("/v2/bans/read", BanInfoV2));
|
||||
Rest.Register(new RestCommand("/v2/bans/destroy", BanDestroyV2));
|
||||
Rest.Register(new SecureRestCommand("/bans/create", BanCreate, RestPermissions.restmanagebans));
|
||||
Rest.Register(new SecureRestCommand("/v2/bans/list", BanListV2, RestPermissions.restviewbans));
|
||||
Rest.Register(new SecureRestCommand("/v2/bans/read", BanInfoV2, RestPermissions.restviewbans));
|
||||
Rest.Register(new SecureRestCommand("/v2/bans/destroy", BanDestroyV2, RestPermissions.restmanagebans));
|
||||
|
||||
// World Commands
|
||||
Rest.Register(new RestCommand("/world/read", WorldRead));
|
||||
Rest.Register(new RestCommand("/world/meteor", WorldMeteor));
|
||||
Rest.Register(new RestCommand("/world/bloodmoon/{bool}", WorldBloodmoon));
|
||||
Rest.Register(new RestCommand("/v2/world/save", WorldSave));
|
||||
Rest.Register(new RestCommand("/v2/world/autosave/state/{bool}", WorldChangeSaveSettings));
|
||||
Rest.Register(new RestCommand("/v2/world/butcher", WorldButcher));
|
||||
Rest.Register(new SecureRestCommand("/world/read", WorldRead));
|
||||
Rest.Register(new SecureRestCommand("/world/meteor", WorldMeteor, RestPermissions.restcauseevents));
|
||||
Rest.Register(new SecureRestCommand("/world/bloodmoon/{bool}", WorldBloodmoon, RestPermissions.restcauseevents));
|
||||
Rest.Register(new SecureRestCommand("/v2/world/save", WorldSave, RestPermissions.restcfg));
|
||||
Rest.Register(new SecureRestCommand("/v2/world/autosave/state/{bool}", WorldChangeSaveSettings, RestPermissions.restcfg));
|
||||
Rest.Register(new SecureRestCommand("/v2/world/butcher", WorldButcher, RestPermissions.restbutcher));
|
||||
|
||||
// Player Commands
|
||||
Rest.Register(new RestCommand("/lists/players", PlayerList));
|
||||
Rest.Register(new RestCommand("/v2/players/list", PlayerListV2));
|
||||
Rest.Register(new RestCommand("/v2/players/read", PlayerReadV2));
|
||||
Rest.Register(new RestCommand("/v2/players/kick", PlayerKickV2));
|
||||
Rest.Register(new RestCommand("/v2/players/ban", PlayerBanV2));
|
||||
Rest.Register(new RestCommand("/v2/players/kill", PlayerKill));
|
||||
Rest.Register(new RestCommand("/v2/players/mute", PlayerMute));
|
||||
Rest.Register(new RestCommand("/v2/players/unmute", PlayerUnMute));
|
||||
Rest.Register(new SecureRestCommand("/lists/players", PlayerList));
|
||||
Rest.Register(new SecureRestCommand("/v2/players/list", PlayerListV2));
|
||||
Rest.Register(new SecureRestCommand("/v2/players/read", PlayerReadV2, RestPermissions.restuserinfo));
|
||||
Rest.Register(new SecureRestCommand("/v2/players/kick", PlayerKickV2, RestPermissions.restkick));
|
||||
Rest.Register(new SecureRestCommand("/v2/players/ban", PlayerBanV2, RestPermissions.restban, RestPermissions.restmanagebans));
|
||||
Rest.Register(new SecureRestCommand("/v2/players/kill", PlayerKill, RestPermissions.restkill));
|
||||
Rest.Register(new SecureRestCommand("/v2/players/mute", PlayerMute, RestPermissions.restmute));
|
||||
Rest.Register(new SecureRestCommand("/v2/players/unmute", PlayerUnMute, RestPermissions.restmute));
|
||||
|
||||
// Group Commands
|
||||
Rest.Register(new RestCommand("/v2/groups/list", GroupList));
|
||||
Rest.Register(new RestCommand("/v2/groups/read", GroupInfo));
|
||||
Rest.Register(new RestCommand("/v2/groups/destroy", GroupDestroy));
|
||||
Rest.Register(new RestCommand("/v2/groups/create", GroupCreate));
|
||||
Rest.Register(new RestCommand("/v2/groups/update", GroupUpdate));
|
||||
Rest.Register(new SecureRestCommand("/v2/groups/list", GroupList, RestPermissions.restviewgroups));
|
||||
Rest.Register(new SecureRestCommand("/v2/groups/read", GroupInfo, RestPermissions.restviewgroups));
|
||||
Rest.Register(new SecureRestCommand("/v2/groups/destroy", GroupDestroy, RestPermissions.restmanagegroups));
|
||||
Rest.Register(new SecureRestCommand("/v2/groups/create", GroupCreate, RestPermissions.restmanagegroups));
|
||||
Rest.Register(new SecureRestCommand("/v2/groups/update", GroupUpdate, RestPermissions.restmanagegroups));
|
||||
}
|
||||
|
||||
#region RestServerMethods
|
||||
|
||||
private object ServerCommand(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object ServerCommand(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(parameters["cmd"]))
|
||||
return RestMissingParam("cmd");
|
||||
|
||||
TSRestPlayer tr = new TSRestPlayer();
|
||||
Group restPlayerGroup;
|
||||
// TODO: Get rid of this when the old REST permission model is removed.
|
||||
if (TShock.Config.RestUseNewPermissionModel)
|
||||
restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
|
||||
else
|
||||
restPlayerGroup = new SuperAdminGroup();
|
||||
|
||||
TSRestPlayer tr = new TSRestPlayer(tokenData.Username, restPlayerGroup);
|
||||
Commands.HandleCommand(tr, parameters["cmd"]);
|
||||
return RestResponse(string.Join("\n", tr.GetCommandOutput()));
|
||||
}
|
||||
|
||||
private object ServerOff(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object ServerCommandV3(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(parameters["cmd"]))
|
||||
return RestMissingParam("cmd");
|
||||
|
||||
Group restPlayerGroup;
|
||||
// TODO: Get rid of this when the old REST permission model is removed.
|
||||
if (TShock.Config.RestUseNewPermissionModel)
|
||||
restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
|
||||
else
|
||||
restPlayerGroup = new SuperAdminGroup();
|
||||
|
||||
TSRestPlayer tr = new TSRestPlayer(tokenData.Username, restPlayerGroup);
|
||||
Commands.HandleCommand(tr, parameters["cmd"]);
|
||||
return new RestObject()
|
||||
{
|
||||
{"response", tr.GetCommandOutput()}
|
||||
};
|
||||
}
|
||||
|
||||
private object ServerOff(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (!GetBool(parameters["confirm"], false))
|
||||
return RestInvalidParam("confirm");
|
||||
|
||||
// Inform players the server is shutting down
|
||||
var msg = string.IsNullOrWhiteSpace(parameters["message"]) ? "Server is shutting down" : parameters["message"];
|
||||
TShock.Utils.StopServer(!GetBool(parameters["nosave"], false), msg);
|
||||
var reason = string.IsNullOrWhiteSpace(parameters["message"]) ? "Server is shutting down" : parameters["message"];
|
||||
TShock.Utils.StopServer(!GetBool(parameters["nosave"], false), reason);
|
||||
|
||||
return RestResponse("The server is shutting down");
|
||||
}
|
||||
|
||||
private object ServerBroadcast(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object ServerRestart(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (!GetBool(parameters["confirm"], false))
|
||||
return RestInvalidParam("confirm");
|
||||
|
||||
// Inform players the server is shutting down
|
||||
var reason = string.IsNullOrWhiteSpace(parameters["message"]) ? "Server is restarting" : parameters["message"];
|
||||
TShock.Utils.RestartServer(!GetBool(parameters["nosave"], false), reason);
|
||||
|
||||
return RestResponse("The server is shutting down and will attempt to restart");
|
||||
}
|
||||
|
||||
private object ServerReload(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
TShock.Utils.Reload(new TSRestPlayer(tokenData.Username, TShock.Groups.GetGroupByName(tokenData.UserGroupName)));
|
||||
|
||||
return RestResponse("Configuration, permissions, and regions reload complete. Some changes may require a server restart.");
|
||||
}
|
||||
|
||||
private object ServerBroadcast(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var msg = parameters["msg"];
|
||||
if (string.IsNullOrWhiteSpace(msg))
|
||||
|
|
@ -118,11 +182,32 @@ namespace TShockAPI
|
|||
return RestResponse("The message was broadcasted successfully");
|
||||
}
|
||||
|
||||
private object ServerStatus(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object ServerMotd(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (TShock.Config.EnableTokenEndpointAuthentication)
|
||||
return RestError("Server settings require a token for this API call");
|
||||
string motdFilePath = Path.Combine(TShock.SavePath, "motd.txt");
|
||||
if (!File.Exists(motdFilePath))
|
||||
return this.RestError("The motd.txt was not found.", "500");
|
||||
|
||||
return new RestObject()
|
||||
{
|
||||
{"motd", File.ReadAllLines(motdFilePath)}
|
||||
};
|
||||
}
|
||||
|
||||
private object ServerRules(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
string rulesFilePath = Path.Combine(TShock.SavePath, "rules.txt");
|
||||
if (!File.Exists(rulesFilePath))
|
||||
return this.RestError("The rules.txt was not found.", "500");
|
||||
|
||||
return new RestObject()
|
||||
{
|
||||
{"rules", File.ReadAllLines(rulesFilePath)}
|
||||
};
|
||||
}
|
||||
|
||||
private object ServerStatus(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var activeplayers = Main.player.Where(p => null != p && p.active).ToList();
|
||||
return new RestObject()
|
||||
{
|
||||
|
|
@ -133,18 +218,17 @@ namespace TShockAPI
|
|||
};
|
||||
}
|
||||
|
||||
private object ServerStatusV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object ServerStatusV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (TShock.Config.EnableTokenEndpointAuthentication)
|
||||
return RestError("Server settings require a token for this API call");
|
||||
|
||||
var ret = new RestObject()
|
||||
{
|
||||
{"name", TShock.Config.ServerName},
|
||||
{"port", TShock.Config.ServerPort},
|
||||
{"playercount", Main.player.Where(p => null != p && p.active).Count()},
|
||||
{"maxplayers", TShock.Config.MaxSlots},
|
||||
{"world", Main.worldName}
|
||||
{"world", Main.worldName},
|
||||
{"uptime", (DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime).ToString(@"d'.'hh':'mm':'ss")},
|
||||
{"serverpassword", !string.IsNullOrEmpty(TShock.Config.ServerPassword)}
|
||||
};
|
||||
|
||||
if (GetBool(parameters["players"], false))
|
||||
|
|
@ -174,52 +258,56 @@ namespace TShockAPI
|
|||
rules.Add("PvPMode", TShock.Config.PvPMode);
|
||||
rules.Add("SpawnProtection", TShock.Config.SpawnProtection);
|
||||
rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius);
|
||||
rules.Add("ServerSideInventory", TShock.Config.ServerSideInventory);
|
||||
|
||||
ret.Add("rules", rules);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private object ServerTokenTest(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object ServerTokenTest(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
return RestResponse("Token is valid and was passed through correctly");
|
||||
return new RestObject()
|
||||
{
|
||||
{"response", "Token is valid and was passed through correctly."},
|
||||
{"associateduser", tokenData.Username}
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RestUserMethods
|
||||
|
||||
private object UserActiveListV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object UserActiveListV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
return new RestObject() { { "activeusers", string.Join("\t", TShock.Players.Where(p => null != p && null != p.UserAccountName && p.Active).Select(p => p.UserAccountName)) } };
|
||||
}
|
||||
|
||||
private object UserListV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object UserListV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
return new RestObject() { { "users", TShock.Users.GetUsers().Select(p => new Dictionary<string,object>(){
|
||||
{"name", p.Name},
|
||||
{"id", p.ID},
|
||||
{"group", p.Group},
|
||||
{"ip", p.Address},
|
||||
}) } };
|
||||
}
|
||||
|
||||
private object UserCreateV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object UserCreateV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var username = parameters["user"];
|
||||
if (string.IsNullOrWhiteSpace(username))
|
||||
return RestMissingParam("user");
|
||||
|
||||
var group = parameters["group"];
|
||||
if (string.IsNullOrWhiteSpace(group))
|
||||
return RestMissingParam("group");
|
||||
if (string.IsNullOrWhiteSpace(group))
|
||||
group = TShock.Config.DefaultRegistrationGroupName;
|
||||
|
||||
var password = parameters["password"];
|
||||
if (string.IsNullOrWhiteSpace(password))
|
||||
return RestMissingParam("password");
|
||||
|
||||
// NOTE: ip can be blank
|
||||
User user = new User(parameters["ip"], username, password, group);
|
||||
User user = new User(username, password, group, "", "");
|
||||
try
|
||||
{
|
||||
TShock.Users.AddUser(user);
|
||||
|
|
@ -232,7 +320,7 @@ namespace TShockAPI
|
|||
return RestResponse("User was successfully created");
|
||||
}
|
||||
|
||||
private object UserUpdateV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object UserUpdateV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = UserFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -274,7 +362,7 @@ namespace TShockAPI
|
|||
return response;
|
||||
}
|
||||
|
||||
private object UserDestroyV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object UserDestroyV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = UserFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -292,7 +380,7 @@ namespace TShockAPI
|
|||
return RestResponse("User deleted successfully");
|
||||
}
|
||||
|
||||
private object UserInfoV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object UserInfoV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = UserFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -306,7 +394,7 @@ namespace TShockAPI
|
|||
|
||||
#region RestBanMethods
|
||||
|
||||
private object BanCreate(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object BanCreate(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ip = parameters["ip"];
|
||||
var name = parameters["name"];
|
||||
|
|
@ -316,7 +404,7 @@ namespace TShockAPI
|
|||
|
||||
try
|
||||
{
|
||||
TShock.Bans.AddBan(ip, name, parameters["reason"], true);
|
||||
TShock.Bans.AddBan(ip, name, parameters["reason"], true, tokenData.Username);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -325,7 +413,7 @@ namespace TShockAPI
|
|||
return RestResponse("Ban created successfully");
|
||||
}
|
||||
|
||||
private object BanDestroyV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object BanDestroyV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = BanFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -357,7 +445,7 @@ namespace TShockAPI
|
|||
return RestResponse("Ban deleted successfully");
|
||||
}
|
||||
|
||||
private object BanInfoV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object BanInfoV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = BanFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -371,7 +459,7 @@ namespace TShockAPI
|
|||
};
|
||||
}
|
||||
|
||||
private object BanListV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object BanListV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var banList = new ArrayList();
|
||||
foreach (var ban in TShock.Bans.GetBans())
|
||||
|
|
@ -393,7 +481,7 @@ namespace TShockAPI
|
|||
|
||||
#region RestWorldMethods
|
||||
|
||||
private object WorldChangeSaveSettings(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object WorldChangeSaveSettings(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
bool autoSave;
|
||||
if (!bool.TryParse(verbs["bool"], out autoSave))
|
||||
|
|
@ -403,14 +491,14 @@ namespace TShockAPI
|
|||
return RestResponse("AutoSave has been set to " + autoSave);
|
||||
}
|
||||
|
||||
private object WorldSave(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object WorldSave(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
SaveManager.Instance.SaveWorld();
|
||||
|
||||
return RestResponse("World saved");
|
||||
}
|
||||
|
||||
private object WorldButcher(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object WorldButcher(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
bool killFriendly;
|
||||
if (!bool.TryParse(parameters["killfriendly"], out killFriendly))
|
||||
|
|
@ -432,7 +520,7 @@ namespace TShockAPI
|
|||
return RestResponse(killcount + " NPCs have been killed");
|
||||
}
|
||||
|
||||
private object WorldRead(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object WorldRead(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
return new RestObject()
|
||||
{
|
||||
|
|
@ -445,7 +533,7 @@ namespace TShockAPI
|
|||
};
|
||||
}
|
||||
|
||||
private object WorldMeteor(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object WorldMeteor(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (null == WorldGen.genRand)
|
||||
WorldGen.genRand = new Random();
|
||||
|
|
@ -453,7 +541,7 @@ namespace TShockAPI
|
|||
return RestResponse("Meteor has been spawned");
|
||||
}
|
||||
|
||||
private object WorldBloodmoon(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object WorldBloodmoon(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
bool bloodmoon;
|
||||
if (!bool.TryParse(verbs["bool"], out bloodmoon))
|
||||
|
|
@ -467,23 +555,23 @@ namespace TShockAPI
|
|||
|
||||
#region RestPlayerMethods
|
||||
|
||||
private object PlayerUnMute(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object PlayerUnMute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
return PlayerSetMute(parameters, false);
|
||||
}
|
||||
|
||||
private object PlayerMute(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object PlayerMute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
return PlayerSetMute(parameters, true);
|
||||
}
|
||||
|
||||
private object PlayerList(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object PlayerList(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var activeplayers = Main.player.Where(p => null != p && p.active).ToList();
|
||||
return new RestObject() { { "players", string.Join(", ", activeplayers.Select(p => p.name)) } };
|
||||
}
|
||||
|
||||
private object PlayerListV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object PlayerListV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var playerList = new ArrayList();
|
||||
foreach (TSPlayer tsPlayer in TShock.Players.Where(p => null != p))
|
||||
|
|
@ -495,7 +583,7 @@ namespace TShockAPI
|
|||
return new RestObject() { { "players", playerList } };
|
||||
}
|
||||
|
||||
private object PlayerReadV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object PlayerReadV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = PlayerFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -515,7 +603,7 @@ namespace TShockAPI
|
|||
};
|
||||
}
|
||||
|
||||
private object PlayerKickV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object PlayerKickV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = PlayerFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -526,7 +614,7 @@ namespace TShockAPI
|
|||
return RestResponse("Player " + player.Name + " was kicked");
|
||||
}
|
||||
|
||||
private object PlayerBanV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object PlayerBanV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = PlayerFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -539,7 +627,7 @@ namespace TShockAPI
|
|||
return RestResponse("Player " + player.Name + " was banned");
|
||||
}
|
||||
|
||||
private object PlayerKill(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object PlayerKill(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = PlayerFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -556,7 +644,7 @@ namespace TShockAPI
|
|||
|
||||
#region RestGroupMethods
|
||||
|
||||
private object GroupList(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object GroupList(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var groups = new ArrayList();
|
||||
foreach (Group group in TShock.Groups)
|
||||
|
|
@ -566,7 +654,7 @@ namespace TShockAPI
|
|||
return new RestObject() { { "groups", groups } };
|
||||
}
|
||||
|
||||
private object GroupInfo(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object GroupInfo(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = GroupFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -583,7 +671,7 @@ namespace TShockAPI
|
|||
};
|
||||
}
|
||||
|
||||
private object GroupDestroy(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object GroupDestroy(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = GroupFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -602,7 +690,7 @@ namespace TShockAPI
|
|||
return RestResponse("Group '" + group.Name + "' deleted successfully");
|
||||
}
|
||||
|
||||
private object GroupCreate(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object GroupCreate(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var name = parameters["group"];
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
|
|
@ -619,7 +707,7 @@ namespace TShockAPI
|
|||
return RestResponse("Group '" + name + "' created successfully");
|
||||
}
|
||||
|
||||
private object GroupUpdate(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object GroupUpdate(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var ret = GroupFind(parameters);
|
||||
if (ret is RestObject)
|
||||
|
|
@ -713,10 +801,6 @@ namespace TShockAPI
|
|||
break;
|
||||
case "id":
|
||||
user = TShock.Users.GetUserByID(Convert.ToInt32(name));
|
||||
break;
|
||||
case "ip":
|
||||
user = TShock.Users.GetUserByIP(name);
|
||||
|
||||
break;
|
||||
default:
|
||||
return RestError("Invalid Type: '" + type + "'");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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;
|
||||
|
||||
|
|
|
|||
87
TShockAPI/Rest/RestPermissions.cs
Normal file
87
TShockAPI/Rest/RestPermissions.cs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Rests
|
||||
{
|
||||
public static class RestPermissions
|
||||
{
|
||||
// tshock.rest.bans nodes
|
||||
|
||||
[Description("REST user can list and get detailed information about bans.")]
|
||||
public static readonly string restviewbans = "tshock.rest.bans.view";
|
||||
|
||||
[Description("REST user can alter bans.")]
|
||||
public static readonly string restmanagebans = "tshock.rest.bans.manage";
|
||||
|
||||
// tshock.rest.groups nodes
|
||||
|
||||
[Description("REST user can list and get detailed information about groups.")]
|
||||
public static readonly string restviewgroups = "tshock.rest.groups.view";
|
||||
|
||||
[Description("REST user can alter groups.")]
|
||||
public static readonly string restmanagegroups = "tshock.rest.groups.manage";
|
||||
|
||||
// tshock.rest.users nodes
|
||||
|
||||
[Description("REST user can list and get detailed information about users.")]
|
||||
public static readonly string restviewusers = "tshock.rest.users.view";
|
||||
|
||||
[Description("REST user can alter users.")]
|
||||
public static readonly string restmanageusers = "tshock.rest.users.manage";
|
||||
|
||||
[Description("REST user can get user information.")]
|
||||
public static readonly string restuserinfo = "tshock.rest.users.info";
|
||||
|
||||
// Non-grouped nodes
|
||||
|
||||
[Description("User can create REST tokens.")]
|
||||
public static readonly string restapi = "tshock.rest.useapi";
|
||||
|
||||
[Description("User or REST user can destroy all REST tokens.")]
|
||||
public static readonly string restmanage = "tshock.rest.manage";
|
||||
|
||||
[Description("REST user can turn off / restart the server.")]
|
||||
public static readonly string restmaintenance = "tshock.rest.maintenance";
|
||||
|
||||
[Description("REST user can reload configurations, save the world and set auto save settings.")]
|
||||
public static readonly string restcfg = "tshock.rest.cfg";
|
||||
|
||||
[Description("REST user can kick players.")]
|
||||
public static readonly string restkick = "tshock.rest.kick";
|
||||
|
||||
[Description("REST user can ban players.")]
|
||||
public static readonly string restban = "tshock.rest.ban";
|
||||
|
||||
[Description("REST user can mute and unmute players.")]
|
||||
public static readonly string restmute = "tshock.rest.mute";
|
||||
|
||||
[Description("REST user can kill players.")]
|
||||
public static readonly string restkill = "tshock.rest.kill";
|
||||
|
||||
[Description("REST user can drop meteors or change bloodmoon.")]
|
||||
public static readonly string restcauseevents = "tshock.rest.causeevents";
|
||||
|
||||
[Description("REST user can butcher npcs.")]
|
||||
public static readonly string restbutcher = "tshock.rest.butcher";
|
||||
|
||||
[Description("REST user can run raw TShock commands (the raw command permissions are also checked though).")]
|
||||
public static readonly string restrawcommand = "tshock.rest.command";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,41 +15,76 @@ 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.Linq;
|
||||
using System.Net;
|
||||
using HttpServer;
|
||||
using TShockAPI;
|
||||
using TShockAPI.DB;
|
||||
|
||||
namespace Rests
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="username">Username to verify</param>
|
||||
/// <param name="password">Password to verify</param>
|
||||
/// <returns>Returning a restobject with a null error means a successful verification.</returns>
|
||||
public delegate RestObject VerifyD(string username, string password);
|
||||
|
||||
public class SecureRest : Rest
|
||||
{
|
||||
public Dictionary<string, object> Tokens { get; protected set; }
|
||||
public event VerifyD Verify;
|
||||
public struct TokenData
|
||||
{
|
||||
public static readonly TokenData None = default(TokenData);
|
||||
|
||||
public string Username { get; set; }
|
||||
public string UserGroupName { get; set; }
|
||||
}
|
||||
|
||||
public Dictionary<string,TokenData> Tokens { get; protected set; }
|
||||
public Dictionary<string, TokenData> AppTokens { get; protected set; }
|
||||
|
||||
public SecureRest(IPAddress ip, int port)
|
||||
: base(ip, port)
|
||||
{
|
||||
Tokens = new Dictionary<string, object>();
|
||||
Register(new RestCommand("/token/create/{username}/{password}", NewToken) {RequiresToken = false});
|
||||
Register(new RestCommand("/v2/token/create/{password}", NewTokenV2) { RequiresToken = false });
|
||||
Register(new RestCommand("/token/destroy/{token}", DestroyToken) {RequiresToken = true});
|
||||
foreach (KeyValuePair<string, string> t in TShockAPI.TShock.RESTStartupTokens)
|
||||
Tokens = new Dictionary<string, TokenData>();
|
||||
AppTokens = new Dictionary<string, TokenData>();
|
||||
|
||||
Register(new RestCommand("/token/create/{username}/{password}", NewToken) { DoLog = false });
|
||||
Register(new RestCommand("/v2/token/create/{password}", NewTokenV2) { DoLog = false });
|
||||
Register(new SecureRestCommand("/token/destroy/{token}", DestroyToken));
|
||||
Register(new SecureRestCommand("/v3/token/destroy/all", DestroyAllTokens, RestPermissions.restmanage));
|
||||
|
||||
foreach (KeyValuePair<string, TokenData> t in TShockAPI.TShock.RESTStartupTokens)
|
||||
{
|
||||
Tokens.Add(t.Key, t.Value);
|
||||
AppTokens.Add(t.Key, t.Value);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, TokenData> t in TShock.Config.ApplicationRestTokens)
|
||||
{
|
||||
AppTokens.Add(t.Key, t.Value);
|
||||
}
|
||||
|
||||
// TODO: Get rid of this when the old REST permission model is removed.
|
||||
if (TShock.Config.RestApiEnabled && !TShock.Config.RestUseNewPermissionModel)
|
||||
{
|
||||
string warningMessage = string.Concat(
|
||||
"You're using the old REST permission model which is highly vulnerable in matter of security. ",
|
||||
"The old model will be removed with the next maintenance release of TShock. In order to switch to the new model, ",
|
||||
"change the config setting \"RestUseNewPermissionModel\" to true."
|
||||
);
|
||||
Log.Warn(warningMessage);
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(warningMessage);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
}
|
||||
else if (TShock.Config.RestApiEnabled)
|
||||
{
|
||||
string warningMessage = string.Concat(
|
||||
"You're using the new more secure REST permission model which can lead to compatibility problems ",
|
||||
"with existing REST services. If compatibility problems occur, you can switch back to the unsecure permission ",
|
||||
"model by changing the config setting \"RestUseNewPermissionModel\" to false, which is not recommended."
|
||||
);
|
||||
Log.ConsoleInfo(warningMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private object DestroyToken(RestVerbs verbs, IParameterCollection parameters)
|
||||
private object DestroyToken(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
var token = verbs["token"];
|
||||
try
|
||||
|
|
@ -58,11 +93,19 @@ namespace Rests
|
|||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{{"status", "400"}, {"error", "The specified token queued for destruction failed to be deleted."}};
|
||||
return new RestObject("400")
|
||||
{ Error = "The specified token queued for destruction failed to be deleted." };
|
||||
}
|
||||
return new Dictionary<string, string>
|
||||
{{"status", "200"}, {"response", "Requested token was successfully destroyed."}};
|
||||
return new RestObject()
|
||||
{ Response = "Requested token was successfully destroyed." };
|
||||
}
|
||||
|
||||
private object DestroyAllTokens(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
Tokens.Clear();
|
||||
|
||||
return new RestObject()
|
||||
{ Response = "All tokens were successfully destroyed." };
|
||||
}
|
||||
|
||||
private object NewTokenV2(RestVerbs verbs, IParameterCollection parameters)
|
||||
|
|
@ -70,29 +113,7 @@ namespace Rests
|
|||
var user = parameters["username"];
|
||||
var pass = verbs["password"];
|
||||
|
||||
RestObject obj = null;
|
||||
if (Verify != null)
|
||||
obj = Verify(user, pass);
|
||||
|
||||
if (obj == null)
|
||||
obj = new RestObject("401") { Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." };
|
||||
|
||||
if (obj.Error != null)
|
||||
return obj;
|
||||
|
||||
string hash;
|
||||
var rand = new Random();
|
||||
var randbytes = new byte[32];
|
||||
do
|
||||
{
|
||||
rand.NextBytes(randbytes);
|
||||
hash = randbytes.Aggregate("", (s, b) => s + b.ToString("X2"));
|
||||
} while (Tokens.ContainsKey(hash));
|
||||
|
||||
Tokens.Add(hash, user);
|
||||
|
||||
obj["token"] = hash;
|
||||
return obj;
|
||||
return this.NewTokenInternal(user, pass);
|
||||
}
|
||||
|
||||
private object NewToken(RestVerbs verbs, IParameterCollection parameters)
|
||||
|
|
@ -100,55 +121,83 @@ namespace Rests
|
|||
var user = verbs["username"];
|
||||
var pass = verbs["password"];
|
||||
|
||||
RestObject obj = null;
|
||||
if (Verify != null)
|
||||
obj = Verify(user, pass);
|
||||
RestObject response = this.NewTokenInternal(user, pass);
|
||||
response["deprecated"] = "This endpoint is depracted and will be removed in the future.";
|
||||
return response;
|
||||
}
|
||||
|
||||
if (obj == null)
|
||||
obj = new RestObject("401")
|
||||
{Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair."};
|
||||
private RestObject NewTokenInternal(string username, string password)
|
||||
{
|
||||
User userAccount = TShock.Users.GetUserByName(username);
|
||||
if (userAccount == null)
|
||||
return new RestObject("401") { Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." };
|
||||
|
||||
if (!TShock.Utils.HashPassword(password).Equals(userAccount.Password, StringComparison.InvariantCultureIgnoreCase))
|
||||
return new RestObject("401")
|
||||
{ Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." };
|
||||
|
||||
if (obj.Error != null)
|
||||
return obj;
|
||||
|
||||
string hash;
|
||||
Group userGroup = TShock.Utils.GetGroup(userAccount.Group);
|
||||
if (!userGroup.HasPermission(RestPermissions.restapi) && userAccount.Group != "superadmin")
|
||||
return new RestObject("403")
|
||||
{ Error = "Although your account was successfully found and identified, your account lacks the permission required to use the API. (restapi)" };
|
||||
|
||||
string tokenHash;
|
||||
var rand = new Random();
|
||||
var randbytes = new byte[32];
|
||||
do
|
||||
{
|
||||
rand.NextBytes(randbytes);
|
||||
hash = randbytes.Aggregate("", (s, b) => s + b.ToString("X2"));
|
||||
} while (Tokens.ContainsKey(hash));
|
||||
tokenHash = randbytes.Aggregate("", (s, b) => s + b.ToString("X2"));
|
||||
} while (Tokens.ContainsKey(tokenHash));
|
||||
|
||||
Tokens.Add(hash, user);
|
||||
Tokens.Add(tokenHash, new TokenData { Username = userAccount.Name, UserGroupName = userGroup.Name });
|
||||
|
||||
obj["token"] = hash;
|
||||
obj["deprecated"] = "This method will be removed from TShock in 3.6.";
|
||||
return obj;
|
||||
RestObject response = new RestObject() { Response = "Successful login" };
|
||||
response["token"] = tokenHash;
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
||||
{
|
||||
if (cmd.RequiresToken)
|
||||
{
|
||||
var strtoken = parms["token"];
|
||||
if (strtoken == null)
|
||||
return new Dictionary<string, string>
|
||||
{{"status", "401"}, {"error", "Not authorized. The specified API endpoint requires a token."}};
|
||||
if (!cmd.RequiresToken)
|
||||
return base.ExecuteCommand(cmd, verbs, parms);
|
||||
|
||||
var token = parms["token"];
|
||||
if (token == null)
|
||||
return new RestObject("401")
|
||||
{ Error = "Not authorized. The specified API endpoint requires a token." };
|
||||
|
||||
object token;
|
||||
if (!Tokens.TryGetValue(strtoken, out token))
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
{"status", "403"},
|
||||
{
|
||||
"error",
|
||||
"Not authorized. The specified API endpoint requires a token, but the provided token was not valid."
|
||||
}
|
||||
};
|
||||
SecureRestCommand secureCmd = (SecureRestCommand)cmd;
|
||||
TokenData tokenData;
|
||||
if (!Tokens.TryGetValue(token, out tokenData) && !AppTokens.TryGetValue(token, out tokenData))
|
||||
return new RestObject("403")
|
||||
{ Error = "Not authorized. The specified API endpoint requires a token, but the provided token was not valid." };
|
||||
|
||||
// TODO: Get rid of this when the old REST permission model is removed.
|
||||
if (TShock.Config.RestUseNewPermissionModel) {
|
||||
Group userGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
|
||||
if (userGroup == null)
|
||||
{
|
||||
Tokens.Remove(token);
|
||||
|
||||
return new RestObject("403")
|
||||
{ Error = "Not authorized. The provided token became invalid due to group changes, please create a new token." };
|
||||
}
|
||||
|
||||
if (secureCmd.Permissions.Length > 0 && secureCmd.Permissions.All(perm => !userGroup.HasPermission(perm)))
|
||||
{
|
||||
return new RestObject("403")
|
||||
{ Error = string.Format("Not authorized. User \"{0}\" has no access to use the specified API endpoint.", tokenData.Username) };
|
||||
}
|
||||
}
|
||||
return base.ExecuteCommand(cmd, verbs, parms);
|
||||
|
||||
object result = secureCmd.Execute(verbs, parms, tokenData);
|
||||
if (cmd.DoLog)
|
||||
TShock.Utils.SendLogs(string.Format(
|
||||
"\"{0}\" requested REST endpoint: {1}", tokenData.Username, this.BuildRequestUri(cmd, verbs, parms, false)),
|
||||
Color.PaleVioletRed);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,24 @@
|
|||
using System;
|
||||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using Terraria;
|
||||
|
||||
namespace TShockAPI
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using Terraria;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
public class StatTracker
|
||||
{
|
||||
private Utils Utils = TShock.Utils;
|
||||
public DateTime lastcheck = DateTime.MinValue;
|
||||
private readonly int checkinFrequency = 5;
|
||||
|
||||
public void CheckIn()
|
||||
{
|
||||
if ((DateTime.Now - lastcheck).TotalMinutes >= checkinFrequency)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(CallHome);
|
||||
lastcheck = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
private void CallHome(object state)
|
||||
{
|
||||
string fp;
|
||||
string lolpath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/.tshock/";
|
||||
if (!Directory.Exists(lolpath))
|
||||
{
|
||||
Directory.CreateDirectory(lolpath);
|
||||
}
|
||||
if (!File.Exists(Path.Combine(lolpath, Netplay.serverPort + ".fingerprint")))
|
||||
{
|
||||
fp = "";
|
||||
int random = Utils.Random.Next(500000, 1000000);
|
||||
fp += random;
|
||||
|
||||
fp = Utils.HashPassword(Netplay.serverIP + fp + Netplay.serverPort + Netplay.serverListenIP);
|
||||
TextWriter tw = new StreamWriter(Path.Combine(lolpath, Netplay.serverPort + ".fingerprint"));
|
||||
tw.Write(fp);
|
||||
tw.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = "";
|
||||
TextReader tr = new StreamReader(Path.Combine(lolpath, Netplay.serverPort + ".fingerprint"));
|
||||
fp = tr.ReadToEnd();
|
||||
tr.Close();
|
||||
}
|
||||
|
||||
using (var client = new WebClient())
|
||||
{
|
||||
client.Headers.Add("user-agent",
|
||||
"TShock (" + TShock.VersionNum + ")");
|
||||
try
|
||||
{
|
||||
string response;
|
||||
if (TShock.Config.DisablePlayerCountReporting)
|
||||
{
|
||||
response =
|
||||
client.DownloadString("http://tshock.co/tickto.php?do=log&fp=" + fp + "&ver=" + TShock.VersionNum + "&os=" +
|
||||
Environment.OSVersion + "&mono=" + Main.runningMono + "&port=" + Netplay.serverPort +
|
||||
"&plcount=0");
|
||||
}
|
||||
else
|
||||
{
|
||||
response =
|
||||
client.DownloadString("http://tshock.co/tickto.php?do=log&fp=" + fp + "&ver=" + TShock.VersionNum + "&os=" +
|
||||
Environment.OSVersion + "&mono=" + Main.runningMono + "&port=" + Netplay.serverPort +
|
||||
"&plcount=" + TShock.Utils.ActivePlayers());
|
||||
}
|
||||
if (!TShock.Config.HideStatTrackerDebugMessages)
|
||||
Log.ConsoleInfo("Stat Tracker: " + response);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
|
@ -71,10 +72,26 @@ namespace TShockAPI
|
|||
|
||||
public int FirstMaxMP { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The player's group.
|
||||
/// </summary>
|
||||
public Group Group { get; set; }
|
||||
/// <summary>
|
||||
/// The player's group.
|
||||
/// </summary>
|
||||
public Group Group
|
||||
{
|
||||
get
|
||||
{
|
||||
if (tempGroup != null)
|
||||
return tempGroup;
|
||||
return group;
|
||||
}
|
||||
set { group = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The player's temporary group. This overrides the user's actual group.
|
||||
/// </summary>
|
||||
public Group tempGroup = null;
|
||||
|
||||
private Group group = null;
|
||||
|
||||
public bool ReceivedInfo { get; set; }
|
||||
|
||||
|
|
@ -105,6 +122,8 @@ namespace TShockAPI
|
|||
|
||||
public bool AwaitingName { get; set; }
|
||||
|
||||
public string[] AwaitingNameParameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The last time a player broke a grief check.
|
||||
/// </summary>
|
||||
|
|
@ -144,15 +163,21 @@ namespace TShockAPI
|
|||
public string UserAccountName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unused can be removed.
|
||||
/// Whether the player performed a valid login attempt (i.e. entered valid user name and password) but is still blocked
|
||||
/// from logging in because of SSI.
|
||||
/// </summary>
|
||||
public bool HasBeenSpammedWithBuildMessage;
|
||||
public bool LoginFailsBySsi { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the player is logged in or not.
|
||||
/// </summary>
|
||||
public bool IsLoggedIn;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the player has sent their whole inventory to the server while connecting.
|
||||
/// </summary>
|
||||
public bool HasSentInventory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The player's user id( from the db ).
|
||||
/// </summary>
|
||||
|
|
@ -215,6 +240,8 @@ namespace TShockAPI
|
|||
|
||||
public bool SilentKickInProgress;
|
||||
|
||||
public bool SilentJoinInProgress;
|
||||
|
||||
/// <summary>
|
||||
/// A list of points where ice tiles have been placed.
|
||||
/// </summary>
|
||||
|
|
@ -381,7 +408,7 @@ namespace TShockAPI
|
|||
TilesDestroyed = new Dictionary<Vector2, TileData>();
|
||||
TilesCreated = new Dictionary<Vector2, TileData>();
|
||||
Index = index;
|
||||
Group = new Group(TShock.Config.DefaultGuestGroupName);
|
||||
Group = Group.DefaultGroup;
|
||||
IceTiles = new List<Point>();
|
||||
AwaitingResponse = new Dictionary<string, Action<object>>();
|
||||
}
|
||||
|
|
@ -392,7 +419,7 @@ namespace TShockAPI
|
|||
TilesCreated = new Dictionary<Vector2, TileData>();
|
||||
Index = -1;
|
||||
FakePlayer = new Player {name = playerName, whoAmi = -1};
|
||||
Group = new Group(TShock.Config.DefaultGuestGroupName);
|
||||
Group = Group.DefaultGroup;
|
||||
AwaitingResponse = new Dictionary<string, Action<object>>();
|
||||
}
|
||||
|
||||
|
|
@ -557,7 +584,8 @@ namespace TShockAPI
|
|||
|
||||
public bool GiveItemCheck(int type, string name, int width, int height, int stack, int prefix = 0)
|
||||
{
|
||||
if (TShock.Itembans.ItemIsBanned(name) && TShock.Config.PreventBannedItemSpawn)
|
||||
if ((TShock.Itembans.ItemIsBanned(name) && TShock.Config.PreventBannedItemSpawn) &&
|
||||
(TShock.Itembans.ItemIsBanned(name, this) || !TShock.Config.AllowAllowedGroupsToSpawnBannedItems))
|
||||
return false;
|
||||
|
||||
GiveItem(type,name,width,height,stack,prefix);
|
||||
|
|
@ -585,21 +613,41 @@ namespace TShockAPI
|
|||
SendMessage(msg, Color.Yellow);
|
||||
}
|
||||
|
||||
public void SendInfoMessage(string format, params object[] args)
|
||||
{
|
||||
SendInfoMessage(string.Format(format, args));
|
||||
}
|
||||
|
||||
public virtual void SendSuccessMessage(string msg)
|
||||
{
|
||||
SendMessage(msg, Color.Green);
|
||||
}
|
||||
|
||||
public void SendSuccessMessage(string format, params object[] args)
|
||||
{
|
||||
SendSuccessMessage(string.Format(format, args));
|
||||
}
|
||||
|
||||
public virtual void SendWarningMessage(string msg)
|
||||
{
|
||||
SendMessage(msg, Color.OrangeRed);
|
||||
}
|
||||
|
||||
public void SendWarningMessage(string format, params object[] args)
|
||||
{
|
||||
SendWarningMessage(string.Format(format, args));
|
||||
}
|
||||
|
||||
public virtual void SendErrorMessage(string msg)
|
||||
{
|
||||
SendMessage(msg, Color.Red);
|
||||
}
|
||||
|
||||
public void SendErrorMessage(string format, params object[] args)
|
||||
{
|
||||
SendErrorMessage(string.Format(format, args));
|
||||
}
|
||||
|
||||
[Obsolete("Use SendErrorMessage, SendInfoMessage, or SendWarningMessage, or a custom color instead.")]
|
||||
public virtual void SendMessage(string msg)
|
||||
{
|
||||
|
|
@ -712,14 +760,14 @@ namespace TShockAPI
|
|||
}
|
||||
}
|
||||
|
||||
public class TSRestPlayer : TSServerPlayer
|
||||
public class TSRestPlayer : TSPlayer
|
||||
{
|
||||
internal List<string> CommandReturn = new List<string>();
|
||||
internal List<string> CommandOutput = new List<string>();
|
||||
|
||||
public TSRestPlayer()
|
||||
public TSRestPlayer(string playerName, Group playerGroup): base(playerName)
|
||||
{
|
||||
Group = new SuperAdminGroup();
|
||||
AwaitingResponse = new Dictionary<string, Action<object>>();
|
||||
Group = playerGroup;
|
||||
AwaitingResponse = new Dictionary<string, Action<object>>();
|
||||
}
|
||||
|
||||
public override void SendMessage(string msg)
|
||||
|
|
@ -734,21 +782,43 @@ namespace TShockAPI
|
|||
|
||||
public override void SendMessage(string msg, byte red, byte green, byte blue)
|
||||
{
|
||||
CommandReturn.Add(msg);
|
||||
this.CommandOutput.Add(msg);
|
||||
}
|
||||
|
||||
public override void SendInfoMessage(string msg)
|
||||
{
|
||||
SendMessage(msg, Color.Yellow);
|
||||
}
|
||||
|
||||
public override void SendSuccessMessage(string msg)
|
||||
{
|
||||
SendMessage(msg, Color.Green);
|
||||
}
|
||||
|
||||
public override void SendWarningMessage(string msg)
|
||||
{
|
||||
SendMessage(msg, Color.OrangeRed);
|
||||
}
|
||||
|
||||
public override void SendErrorMessage(string msg)
|
||||
{
|
||||
SendMessage(msg, Color.Red);
|
||||
}
|
||||
|
||||
public List<string> GetCommandOutput()
|
||||
{
|
||||
return CommandReturn;
|
||||
return this.CommandOutput;
|
||||
}
|
||||
}
|
||||
|
||||
public class TSServerPlayer : TSPlayer
|
||||
{
|
||||
public static string AccountName = "ServerConsole";
|
||||
public TSServerPlayer()
|
||||
: base("Server")
|
||||
{
|
||||
Group = new SuperAdminGroup();
|
||||
UserAccountName = AccountName;
|
||||
}
|
||||
|
||||
public override void SendErrorMessage(string msg)
|
||||
|
|
@ -832,6 +902,10 @@ namespace TShockAPI
|
|||
|
||||
public void StrikeNPC(int npcid, int damage, float knockBack, int hitDirection)
|
||||
{
|
||||
// Main.rand is thread static.
|
||||
if (Main.rand == null)
|
||||
Main.rand = new Random();
|
||||
|
||||
Main.npc[npcid].StrikeNPC(damage, knockBack, hitDirection);
|
||||
NetMessage.SendData((int) PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.ComponentModel;
|
||||
|
|
@ -23,13 +24,14 @@ using System.Diagnostics;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Hooks;
|
||||
using MaxMind;
|
||||
using Mono.Data.Sqlite;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Newtonsoft.Json;
|
||||
using Rests;
|
||||
using Terraria;
|
||||
using TShockAPI.DB;
|
||||
|
|
@ -37,16 +39,18 @@ using TShockAPI.Net;
|
|||
|
||||
namespace TShockAPI
|
||||
{
|
||||
[APIVersion(1, 12)]
|
||||
[APIVersion(1, 13)]
|
||||
public class TShock : TerrariaPlugin
|
||||
{
|
||||
private const string LogFormatDefault = "yyyy-MM-dd_HH-mm-ss";
|
||||
private static string LogFormat = LogFormatDefault;
|
||||
private static bool LogClear = false;
|
||||
public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
public static readonly string VersionCodename = "Welcome to the future.";
|
||||
public static readonly string VersionCodename = "And the great beast rose from its slumber, ready to take on the world again.";
|
||||
|
||||
public static string SavePath = "tshock";
|
||||
private const string LogFormatDefault = "yyyy-MM-dd_HH-mm-ss";
|
||||
private static string LogFormat = LogFormatDefault;
|
||||
private const string LogPathDefault = "tshock";
|
||||
private static string LogPath = LogPathDefault;
|
||||
private static bool LogClear = false;
|
||||
|
||||
public static TSPlayer[] Players = new TSPlayer[Main.maxPlayers];
|
||||
public static BanManager Bans;
|
||||
|
|
@ -66,11 +70,10 @@ namespace TShockAPI
|
|||
public static SecureRest RestApi;
|
||||
public static RestManager RestManager;
|
||||
public static Utils Utils = Utils.Instance;
|
||||
public static StatTracker StatTracker = new StatTracker();
|
||||
/// <summary>
|
||||
/// Used for implementing REST Tokens prior to the REST system starting up.
|
||||
/// </summary>
|
||||
public static Dictionary<string, string> RESTStartupTokens = new Dictionary<string, string>();
|
||||
public static Dictionary<string, SecureRest.TokenData> RESTStartupTokens = new Dictionary<string, SecureRest.TokenData>();
|
||||
|
||||
/// <summary>
|
||||
/// Called after TShock is initialized. Useful for plugins that needs hooks before tshock but also depend on tshock being loaded.
|
||||
|
|
@ -97,6 +100,10 @@ namespace TShockAPI
|
|||
get { return "The administration modification of the future."; }
|
||||
}
|
||||
|
||||
public override string UpdateURL
|
||||
{
|
||||
get { return ""; }
|
||||
}
|
||||
public TShock(Main game)
|
||||
: base(game)
|
||||
{
|
||||
|
|
@ -108,35 +115,57 @@ namespace TShockAPI
|
|||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||
public override void Initialize()
|
||||
{
|
||||
HandleCommandLine(Environment.GetCommandLineArgs());
|
||||
|
||||
if (!Directory.Exists(SavePath))
|
||||
Directory.CreateDirectory(SavePath);
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
string logFilename;
|
||||
try
|
||||
{
|
||||
logFilename = Path.Combine(SavePath, now.ToString(LogFormat)+".log");
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
// Problem with the log format use the default
|
||||
logFilename = Path.Combine(SavePath, now.ToString(LogFormatDefault) + ".log");
|
||||
}
|
||||
HandleCommandLine(Environment.GetCommandLineArgs());
|
||||
|
||||
if (Version.Major >= 4)
|
||||
getTShockAscii();
|
||||
|
||||
if (!Directory.Exists(SavePath))
|
||||
Directory.CreateDirectory(SavePath);
|
||||
|
||||
ConfigFile.ConfigRead += OnConfigRead;
|
||||
FileTools.SetupConfig();
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
string logFilename;
|
||||
string logPathSetupWarning = null;
|
||||
// Log path was not already set by the command line parameter?
|
||||
if (LogPath == LogPathDefault)
|
||||
LogPath = Config.LogPath;
|
||||
try
|
||||
{
|
||||
logFilename = Path.Combine(LogPath, now.ToString(LogFormat)+".log");
|
||||
if (!Directory.Exists(LogPath))
|
||||
Directory.CreateDirectory(LogPath);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
logPathSetupWarning = "Could not apply the given log path / log format, defaults will be used. Exception details:\n" + ex;
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(logPathSetupWarning);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
// Problem with the log path or format use the default
|
||||
logFilename = Path.Combine(LogPathDefault, now.ToString(LogFormatDefault) + ".log");
|
||||
}
|
||||
#if DEBUG
|
||||
Log.Initialize(logFilename, LogLevel.All, false);
|
||||
Log.Initialize(logFilename, LogLevel.All, false);
|
||||
#else
|
||||
Log.Initialize(logFilename, LogLevel.All & ~LogLevel.Debug, LogClear);
|
||||
Log.Initialize(logFilename, LogLevel.All & ~LogLevel.Debug, LogClear);
|
||||
#endif
|
||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||
|
||||
if (Version.Major >= 4)
|
||||
{
|
||||
getTShockAscii();
|
||||
}
|
||||
if (logPathSetupWarning != null)
|
||||
Log.Warn(logPathSetupWarning);
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
// Will be handled by the server api and written to its crashlog.txt.
|
||||
throw new Exception("Fatal TShock initialization exception. See inner exception for details.", ex);
|
||||
}
|
||||
|
||||
// Further exceptions are written to TShock's log from now on.
|
||||
try
|
||||
{
|
||||
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
|
||||
|
|
@ -147,9 +176,6 @@ namespace TShockAPI
|
|||
}
|
||||
File.WriteAllText(Path.Combine(SavePath, "tshock.pid"), Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
ConfigFile.ConfigRead += OnConfigRead;
|
||||
FileTools.SetupConfig();
|
||||
|
||||
HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs());
|
||||
|
||||
if (Config.StorageType.ToLower() == "sqlite")
|
||||
|
|
@ -195,7 +221,6 @@ namespace TShockAPI
|
|||
RememberedPos = new RememberedPosManager(DB);
|
||||
InventoryDB = new InventoryManager(DB);
|
||||
RestApi = new SecureRest(Netplay.serverListenIP, Config.RestApiPort);
|
||||
RestApi.Verify += RestApi_Verify;
|
||||
RestApi.Port = Config.RestApiPort;
|
||||
RestManager = new RestManager(RestApi);
|
||||
RestManager.RegisterRestfulCommands();
|
||||
|
|
@ -225,6 +250,7 @@ namespace TShockAPI
|
|||
WorldHooks.SaveWorld += SaveManager.Instance.OnSaveWorld;
|
||||
WorldHooks.ChristmasCheck += OnXmasCheck;
|
||||
NetHooks.NameCollision += NetHooks_NameCollision;
|
||||
TShockAPI.Hooks.PlayerHooks.PlayerPostLogin += OnPlayerLogin;
|
||||
|
||||
GetDataHandlers.InitGetDataHandler();
|
||||
Commands.InitCommands();
|
||||
|
|
@ -269,33 +295,6 @@ namespace TShockAPI
|
|||
// ReSharper restore LocalizableElement
|
||||
}
|
||||
|
||||
private RestObject RestApi_Verify(string username, string password)
|
||||
{
|
||||
var userAccount = Users.GetUserByName(username);
|
||||
if (userAccount == null)
|
||||
{
|
||||
return new RestObject("401")
|
||||
{Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair."};
|
||||
}
|
||||
|
||||
if (Utils.HashPassword(password).ToUpper() != userAccount.Password.ToUpper())
|
||||
{
|
||||
return new RestObject("401")
|
||||
{Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair."};
|
||||
}
|
||||
|
||||
if (!Utils.GetGroup(userAccount.Group).HasPermission(Permissions.restapi) && userAccount.Group != "superadmin")
|
||||
{
|
||||
return new RestObject("403")
|
||||
{
|
||||
Error =
|
||||
"Although your account was successfully found and identified, your account lacks the permission required to use the API. (api)"
|
||||
};
|
||||
}
|
||||
|
||||
return new RestObject("200") {Response = "Successful login"}; //Maybe return some user info too?
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
|
|
@ -326,6 +325,7 @@ namespace TShockAPI
|
|||
WorldHooks.SaveWorld -= SaveManager.Instance.OnSaveWorld;
|
||||
WorldHooks.ChristmasCheck -= OnXmasCheck;
|
||||
NetHooks.NameCollision -= NetHooks_NameCollision;
|
||||
TShockAPI.Hooks.PlayerHooks.PlayerPostLogin -= OnPlayerLogin;
|
||||
|
||||
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
|
||||
{
|
||||
|
|
@ -338,7 +338,31 @@ namespace TShockAPI
|
|||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
void NetHooks_NameCollision(int who, string name, HandledEventArgs e)
|
||||
private void OnPlayerLogin(Hooks.PlayerPostLoginEventArgs args)
|
||||
{
|
||||
User u = Users.GetUserByName(args.Player.UserAccountName);
|
||||
List<String> KnownIps = new List<string>();
|
||||
if (!string.IsNullOrWhiteSpace(u.KnownIps))
|
||||
{
|
||||
KnownIps = JsonConvert.DeserializeObject<List<String>>(u.KnownIps);
|
||||
}
|
||||
|
||||
bool found = KnownIps.Any(s => s.Equals(args.Player.IP));
|
||||
if (!found)
|
||||
{
|
||||
if (KnownIps.Count == 100)
|
||||
{
|
||||
KnownIps.RemoveAt(0);
|
||||
}
|
||||
|
||||
KnownIps.Add(args.Player.IP);
|
||||
}
|
||||
|
||||
u.KnownIps = JsonConvert.SerializeObject(KnownIps, Formatting.Indented);
|
||||
Users.UpdateLogin(u);
|
||||
}
|
||||
|
||||
private void NetHooks_NameCollision(int who, string name, HandledEventArgs e)
|
||||
{
|
||||
string ip = TShock.Utils.GetRealIP(Netplay.serverSock[who].tcpClient.Client.RemoteEndPoint.ToString());
|
||||
foreach (TSPlayer ply in TShock.Players)
|
||||
|
|
@ -369,7 +393,7 @@ namespace TShockAPI
|
|||
return;
|
||||
}
|
||||
|
||||
void OnXmasCheck(ChristmasCheckEventArgs args)
|
||||
private void OnXmasCheck(ChristmasCheckEventArgs args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
|
@ -442,9 +466,13 @@ namespace TShockAPI
|
|||
}
|
||||
break;
|
||||
|
||||
case "-dump":
|
||||
ConfigFile.DumpDescriptions();
|
||||
Permissions.DumpDescriptions();
|
||||
case "-logpath":
|
||||
path = parms[++i];
|
||||
if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1)
|
||||
{
|
||||
LogPath = path;
|
||||
Log.ConsoleInfo("Log path has been set to " + path);
|
||||
}
|
||||
break;
|
||||
|
||||
case "-logformat":
|
||||
|
|
@ -454,6 +482,11 @@ namespace TShockAPI
|
|||
case "-logclear":
|
||||
bool.TryParse(parms[++i], out LogClear);
|
||||
break;
|
||||
|
||||
case "-dump":
|
||||
ConfigFile.DumpDescriptions();
|
||||
Permissions.DumpDescriptions();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -473,7 +506,7 @@ namespace TShockAPI
|
|||
break;
|
||||
case "-rest-token":
|
||||
string token = Convert.ToString(parms[++i]);
|
||||
RESTStartupTokens.Add(token, "null");
|
||||
RESTStartupTokens.Add(token, new SecureRest.TokenData { Username = "null", UserGroupName = "superadmin" });
|
||||
Console.WriteLine("Startup parameter overrode REST token.");
|
||||
break;
|
||||
case "-rest-enabled":
|
||||
|
|
@ -537,7 +570,7 @@ namespace TShockAPI
|
|||
|
||||
Regions.ReloadAllRegions();
|
||||
|
||||
StatTracker.CheckIn();
|
||||
Lighting.lightMode = 2;
|
||||
FixChestStacks();
|
||||
|
||||
|
||||
|
|
@ -545,6 +578,9 @@ namespace TShockAPI
|
|||
|
||||
private void FixChestStacks()
|
||||
{
|
||||
if (Config.IgnoreChestStacksOnLoad)
|
||||
return;
|
||||
|
||||
foreach (Chest chest in Main.chest)
|
||||
{
|
||||
if (chest != null)
|
||||
|
|
@ -564,7 +600,6 @@ namespace TShockAPI
|
|||
private void OnUpdate()
|
||||
{
|
||||
UpdateManager.UpdateProcedureCheck();
|
||||
StatTracker.CheckIn();
|
||||
if (Backups.IsBackupTime)
|
||||
Backups.Backup();
|
||||
//call these every second, not every update
|
||||
|
|
@ -735,16 +770,8 @@ namespace TShockAPI
|
|||
private void OnConnect(int ply, HandledEventArgs handler)
|
||||
{
|
||||
var player = new TSPlayer(ply);
|
||||
if (Config.EnableDNSHostResolution)
|
||||
{
|
||||
player.Group = Users.GetGroupForIPExpensive(player.IP);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.Group = Users.GetGroupForIP(player.IP);
|
||||
}
|
||||
|
||||
if (Utils.ActivePlayers() + 1 > Config.MaxSlots + 20)
|
||||
if (Utils.ActivePlayers() + 1 > Config.MaxSlots + Config.ReservedSlots)
|
||||
{
|
||||
Utils.ForceKick(player, Config.ServerFullNoReservedReason, true, false);
|
||||
handler.Handled = true;
|
||||
|
|
@ -758,9 +785,14 @@ namespace TShockAPI
|
|||
|
||||
if (ban != null)
|
||||
{
|
||||
Utils.ForceKick(player, string.Format("You are banned: {0}", ban.Reason), true, false);
|
||||
handler.Handled = true;
|
||||
return;
|
||||
if (!Utils.HasBanExpired(ban))
|
||||
{
|
||||
DateTime exp;
|
||||
string duration = DateTime.TryParse(ban.Expiration, out exp) ? String.Format("until {0}", exp.ToString("G")) : "forever";
|
||||
Utils.ForceKick(player, string.Format("You are banned {0}: {1}", duration, ban.Reason), true, false);
|
||||
handler.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FileTools.OnWhitelist(player.IP))
|
||||
|
|
@ -811,9 +843,13 @@ namespace TShockAPI
|
|||
|
||||
if (ban != null)
|
||||
{
|
||||
Utils.ForceKick(player, string.Format("You are banned: {0}", ban.Reason), true, false);
|
||||
handler.Handled = true;
|
||||
return;
|
||||
if (!Utils.HasBanExpired(ban))
|
||||
{
|
||||
DateTime exp;
|
||||
string duration = DateTime.TryParse(ban.Expiration, out exp) ? String.Format("until {0}", exp.ToString("G")) : "forever";
|
||||
Utils.ForceKick(player, string.Format("You are banned {0}: {1}", duration, ban.Reason), true, false);
|
||||
handler.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -825,12 +861,9 @@ namespace TShockAPI
|
|||
|
||||
if (tsplr != null && tsplr.ReceivedInfo)
|
||||
{
|
||||
if (!tsplr.SilentKickInProgress || tsplr.State > 1)
|
||||
if (!tsplr.SilentKickInProgress && tsplr.State >= 3)
|
||||
{
|
||||
if (tsplr.State >= 2)
|
||||
{
|
||||
Utils.Broadcast(tsplr.Name + " left", Color.Yellow);
|
||||
}
|
||||
Utils.Broadcast(tsplr.Name + " left", Color.Yellow);
|
||||
}
|
||||
Log.Info(string.Format("{0} disconnected.", tsplr.Name));
|
||||
|
||||
|
|
@ -1451,12 +1484,12 @@ namespace TShockAPI
|
|||
return (float) Math.Sqrt(num3);
|
||||
}
|
||||
|
||||
public static bool HackedHealth(TSPlayer player)
|
||||
public static bool HackedStats(TSPlayer player)
|
||||
{
|
||||
return (player.TPlayer.statManaMax > 400) ||
|
||||
(player.TPlayer.statMana > 400) ||
|
||||
(player.TPlayer.statLifeMax > 400) ||
|
||||
(player.TPlayer.statLife > 400);
|
||||
return (player.TPlayer.statManaMax > TShock.Config.MaxMana) ||
|
||||
(player.TPlayer.statMana > TShock.Config.MaxMana) ||
|
||||
(player.TPlayer.statLifeMax > TShock.Config.MaxHealth) ||
|
||||
(player.TPlayer.statLife > TShock.Config.MaxHealth);
|
||||
}
|
||||
|
||||
public static bool HackedInventory(TSPlayer player)
|
||||
|
|
|
|||
|
|
@ -61,32 +61,27 @@
|
|||
<HintPath>..\SqlBins\MySql.Data.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="MySql.Web, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\SqlBins\MySql.Web.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>.\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="TerrariaServer, Version=1.0.4.0, Culture=neutral, processorArchitecture=x86">
|
||||
<Reference Include="TerrariaServer, Version=0.0.0.0, Culture=neutral, processorArchitecture=x86">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<ExecutableExtension>.exe</ExecutableExtension>
|
||||
<HintPath>..\TerrariaServerBins\TerrariaServer.exe</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BackupManager.cs" />
|
||||
<Compile Include="DB\RegionManager.cs" />
|
||||
<Compile Include="Hooks\PlayerLoginEvent.cs" />
|
||||
<Compile Include="Hooks\GeneralHooks.cs" />
|
||||
<Compile Include="Hooks\PlayerHooks.cs" />
|
||||
<Compile Include="PaginationTools.cs" />
|
||||
<Compile Include="PluginUpdater\PluginUpdaterThread.cs" />
|
||||
<Compile Include="PluginUpdater\PluginVersionCheck.cs" />
|
||||
<Compile Include="PluginUpdater\VersionInfo.cs" />
|
||||
<Compile Include="Rest\RestPermissions.cs" />
|
||||
<Compile Include="SaveManager.cs" />
|
||||
<Compile Include="DB\BanManager.cs" />
|
||||
<Compile Include="DB\InventoryManager.cs" />
|
||||
|
|
@ -131,7 +126,6 @@
|
|||
<Compile Include="Rest\RestObject.cs" />
|
||||
<Compile Include="Rest\RestVerbs.cs" />
|
||||
<Compile Include="Rest\SecureRest.cs" />
|
||||
<Compile Include="StatTracker.cs" />
|
||||
<Compile Include="Utils.cs" />
|
||||
<Compile Include="TShock.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
@ -185,11 +179,12 @@
|
|||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>"$(ProjectDir)postbuild.bat"</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_StartDate="2011/6/17" BuildVersion_IncrementBeforeBuild="False" />
|
||||
<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.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
extensions: .cs
|
||||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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.Net;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
TShock, a server mod for Terraria
|
||||
Copyright (C) 2011-2012 The TShock Team
|
||||
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,6 +15,7 @@ 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;
|
||||
|
|
@ -24,6 +25,7 @@ using System.Net.Sockets;
|
|||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Terraria;
|
||||
using TShockAPI.DB;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
|
|
@ -217,18 +219,19 @@ namespace TShockAPI
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends message to all users with 'logs' permission.
|
||||
/// Sends message to all players with 'logs' permission.
|
||||
/// </summary>
|
||||
/// <param name="log">Message to send</param>
|
||||
/// <param name="color">Color of the message</param>
|
||||
public void SendLogs(string log, Color color)
|
||||
/// <param name="excludedPlayer">The player to not send the message to.</param>
|
||||
public void SendLogs(string log, Color color, TSPlayer excludedPlayer = null)
|
||||
{
|
||||
Log.Info(log);
|
||||
TSPlayer.Server.SendMessage(log, color);
|
||||
foreach (TSPlayer player in TShock.Players)
|
||||
{
|
||||
if (player != null && player.Active && player.Group.HasPermission(Permissions.logs) && player.DisplayLogs &&
|
||||
TShock.Config.DisableSpewLogs == false)
|
||||
if (player != null && player != excludedPlayer && player.Active && player.Group.HasPermission(Permissions.logs) &&
|
||||
player.DisplayLogs && TShock.Config.DisableSpewLogs == false)
|
||||
player.SendMessage(log, color);
|
||||
}
|
||||
}
|
||||
|
|
@ -304,7 +307,7 @@ namespace TShockAPI
|
|||
tileX = startTileX + Random.Next(tileXRange*-1, tileXRange);
|
||||
tileY = startTileY + Random.Next(tileYRange*-1, tileYRange);
|
||||
j++;
|
||||
} while (TileValid(tileX, tileY) && !TileClear(tileX, tileY));
|
||||
} while (TilePlacementValid(tileX, tileY) && !TileClear(tileX, tileY));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -313,7 +316,7 @@ namespace TShockAPI
|
|||
/// <param name="tileX">Location X</param>
|
||||
/// <param name="tileY">Location Y</param>
|
||||
/// <returns>If the tile is valid</returns>
|
||||
public bool TileValid(int tileX, int tileY)
|
||||
public bool TilePlacementValid(int tileX, int tileY)
|
||||
{
|
||||
return tileX >= 0 && tileX < Main.maxTilesX && tileY >= 0 && tileY < Main.maxTilesY;
|
||||
}
|
||||
|
|
@ -560,6 +563,36 @@ namespace TShockAPI
|
|||
Netplay.disconnect = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the server after kicking all players with a reason message, and optionally saving the world then attempts to
|
||||
/// restart it.
|
||||
/// </summary>
|
||||
/// <param name="save">bool perform a world save before stop (default: true)</param>
|
||||
/// <param name="reason">string reason (default: "Server shutting down!")</param>
|
||||
public void RestartServer(bool save = true, string reason = "Server shutting down!")
|
||||
{
|
||||
if (TShock.Config.ServerSideInventory)
|
||||
foreach (TSPlayer player in TShock.Players)
|
||||
if (player != null && player.IsLoggedIn && !player.IgnoreActionsForClearingTrashCan)
|
||||
TShock.InventoryDB.InsertPlayerData(player);
|
||||
|
||||
StopServer(true, reason);
|
||||
System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads all configuration settings, groups, regions and raises the reload event.
|
||||
/// </summary>
|
||||
public void Reload(TSPlayer player)
|
||||
{
|
||||
FileTools.SetupConfig();
|
||||
TShock.HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs());
|
||||
TShock.Groups.LoadPermisions();
|
||||
TShock.Regions.ReloadAllRegions();
|
||||
Hooks.GeneralHooks.OnReloadEvent(player);
|
||||
}
|
||||
|
||||
#if COMPAT_SIGS
|
||||
[Obsolete("This method is for signature compatibility for external code only")]
|
||||
public void ForceKick(TSPlayer player, string reason)
|
||||
|
|
@ -641,7 +674,7 @@ namespace TShockAPI
|
|||
{
|
||||
string ip = player.IP;
|
||||
string playerName = player.Name;
|
||||
TShock.Bans.AddBan(ip, playerName, reason);
|
||||
TShock.Bans.AddBan(ip, playerName, reason, false, adminUserName);
|
||||
player.Disconnect(string.Format("Banned: {0}", reason));
|
||||
Log.ConsoleInfo(string.Format("Banned {0} for : {1}", playerName, reason));
|
||||
string verb = force ? "force " : "";
|
||||
|
|
@ -654,6 +687,29 @@ namespace TShockAPI
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool HasBanExpired(Ban ban, bool byName = false)
|
||||
{
|
||||
DateTime exp;
|
||||
bool expirationExists = DateTime.TryParse(ban.Expiration, out exp);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ban.Expiration) && (expirationExists) &&
|
||||
(DateTime.Now >= exp))
|
||||
{
|
||||
if (byName)
|
||||
{
|
||||
TShock.Bans.RemoveBan(ban.Name, true, true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
TShock.Bans.RemoveBan(ban.IP, false, false, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows a file to the user.
|
||||
/// </summary>
|
||||
|
|
@ -709,7 +765,7 @@ namespace TShockAPI
|
|||
return TShock.Groups.groups[i];
|
||||
}
|
||||
}
|
||||
return new Group(TShock.Config.DefaultGuestGroupName);
|
||||
return Group.DefaultGroup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -841,5 +897,25 @@ namespace TShockAPI
|
|||
}
|
||||
return new string(returnstr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates boundary points of the given region's rectangle.
|
||||
/// </summary>
|
||||
/// <param name="regionArea">The region's area to enumerate through.</param>
|
||||
/// <returns>The enumerated boundary points.</returns>
|
||||
public IEnumerable<Point> EnumerateRegionBoundaries(Rectangle regionArea)
|
||||
{
|
||||
for (int x = 0; x < regionArea.Width + 1; x++)
|
||||
{
|
||||
yield return new Point(regionArea.Left + x, regionArea.Top);
|
||||
yield return new Point(regionArea.Left + x, regionArea.Bottom);
|
||||
}
|
||||
|
||||
for (int y = 1; y < regionArea.Height; y++)
|
||||
{
|
||||
yield return new Point(regionArea.Left, regionArea.Top + y);
|
||||
yield return new Point(regionArea.Right, regionArea.Top + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue