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.
|
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)
|
* [Github Releases](https://github.com/TShock/TShock/releases)
|
||||||
* [Download Archive](https://github.com/TShock/TShock/downloads)
|
* [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
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Rests;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
{
|
{
|
||||||
|
|
@ -129,7 +132,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
[Description("This will announce a player's location on join")] public bool EnableGeoIP;
|
[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;
|
EnableTokenEndpointAuthentication;
|
||||||
|
|
||||||
[Description("Deprecated. Use ServerName instead.")] public string ServerNickname = "TShock Server";
|
[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("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 clown bomb projectiles from spawning.")] public bool DisableClownBombs;
|
||||||
|
|
||||||
[Description("Disables snow ball projectiles from spawning.")] public bool DisableSnowBalls;
|
[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 banks on SSI.")] public bool DisablePiggybanksOnSSI = false;
|
||||||
|
|
||||||
[Description("Prevent players from interacting with the world if dead.")] public bool PreventDeadModification =
|
[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
|
[Description("Displays chat messages above players' heads, but will disable chat prefixes to compensate.")] public
|
||||||
bool EnableChatAboveHeads = false;
|
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("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>
|
/// <summary>
|
||||||
/// Reads a configuration file from a given path
|
/// Reads a configuration file from a given path
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
namespace TShockAPI.DB
|
namespace TShockAPI.DB
|
||||||
|
|
@ -34,7 +34,10 @@ namespace TShockAPI.DB
|
||||||
var table = new SqlTable("Bans",
|
var table = new SqlTable("Bans",
|
||||||
new SqlColumn("IP", MySqlDbType.String, 16) {Primary = true},
|
new SqlColumn("IP", MySqlDbType.String, 16) {Primary = true},
|
||||||
new SqlColumn("Name", MySqlDbType.Text),
|
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,
|
var creator = new SqlTableCreator(db,
|
||||||
db.GetSqlType() == SqlType.Sqlite
|
db.GetSqlType() == SqlType.Sqlite
|
||||||
|
|
@ -58,7 +61,7 @@ namespace TShockAPI.DB
|
||||||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE IP=@0", ip))
|
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE IP=@0", ip))
|
||||||
{
|
{
|
||||||
if (reader.Read())
|
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)
|
catch (Exception ex)
|
||||||
|
|
@ -77,7 +80,7 @@ namespace TShockAPI.DB
|
||||||
{
|
{
|
||||||
while (reader.Read())
|
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;
|
return banlist;
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +103,7 @@ namespace TShockAPI.DB
|
||||||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE " + namecol + "=@0", name))
|
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE " + namecol + "=@0", name))
|
||||||
{
|
{
|
||||||
if (reader.Read())
|
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)
|
catch (Exception ex)
|
||||||
|
|
@ -114,14 +117,14 @@ namespace TShockAPI.DB
|
||||||
[Obsolete("This method is for signature compatibility for external code only")]
|
[Obsolete("This method is for signature compatibility for external code only")]
|
||||||
public bool AddBan(string ip, string name, string reason)
|
public bool AddBan(string ip, string name, string reason)
|
||||||
{
|
{
|
||||||
return AddBan(ip, name, reason, false);
|
return AddBan(ip, name, reason, false, "", "");
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -180,11 +183,20 @@ namespace TShockAPI.DB
|
||||||
|
|
||||||
public string Reason { get; set; }
|
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;
|
IP = ip;
|
||||||
Name = name;
|
Name = name;
|
||||||
Reason = reason;
|
Reason = reason;
|
||||||
|
BanningUser = banner;
|
||||||
|
Date = date;
|
||||||
|
Expiration = exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ban()
|
public Ban()
|
||||||
|
|
@ -192,6 +204,9 @@ namespace TShockAPI.DB
|
||||||
IP = string.Empty;
|
IP = string.Empty;
|
||||||
Name = string.Empty;
|
Name = string.Empty;
|
||||||
Reason = string.Empty;
|
Reason = string.Empty;
|
||||||
|
BanningUser = "";
|
||||||
|
Date = "";
|
||||||
|
Expiration = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
|
@ -52,13 +53,29 @@ namespace TShockAPI.DB
|
||||||
LoadPermisions();
|
LoadPermisions();
|
||||||
|
|
||||||
// Add default groups if they don't exist
|
// Add default groups if they don't exist
|
||||||
AddDefaultGroup("guest", "", "canbuild,canregister,canlogin,canpartychat,cantalkinthird");
|
AddDefaultGroup(TShock.Config.DefaultGuestGroupName, "",
|
||||||
AddDefaultGroup("default", "guest", "warp,canchangepassword");
|
string.Join(",", Permissions.canbuild, Permissions.canregister, Permissions.canlogin, Permissions.canpartychat,
|
||||||
AddDefaultGroup("newadmin", "default", "kick,editspawn,reservedslot");
|
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",
|
AddDefaultGroup("admin", "newadmin",
|
||||||
"ban,unban,whitelist,causeevents,spawnboss,spawnmob,managewarp,time,tp,pvpfun,kill,logs,immunetokick,tphere");
|
string.Join(",", Permissions.ban, Permissions.whitelist, Permissions.causeevents, Permissions.spawnboss,
|
||||||
AddDefaultGroup("trustedadmin", "admin", "maintenance,cfg,butcher,item,heal,immunetoban,usebanneditem,manageusers");
|
Permissions.spawnmob, Permissions.managewarp, Permissions.time, Permissions.tp, Permissions.slap,
|
||||||
AddDefaultGroup("vip", "default", "reservedslot");
|
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)
|
private void AddDefaultGroup(string name, string parent, string permissions)
|
||||||
|
|
@ -114,7 +131,7 @@ namespace TShockAPI.DB
|
||||||
if (!string.IsNullOrWhiteSpace(parentname))
|
if (!string.IsNullOrWhiteSpace(parentname))
|
||||||
{
|
{
|
||||||
var parent = groups.FirstOrDefault(gp => gp.Name == 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);
|
var error = "Invalid parent {0} for group {1}".SFormat(parentname, group.Name);
|
||||||
if (exceptions)
|
if (exceptions)
|
||||||
|
|
@ -166,27 +183,40 @@ namespace TShockAPI.DB
|
||||||
/// <param name="chatcolor">chatcolor</param>
|
/// <param name="chatcolor">chatcolor</param>
|
||||||
public void UpdateGroup(string name, string parentname, string permissions, string chatcolor)
|
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);
|
throw new GroupNotExistException(name);
|
||||||
|
|
||||||
Group parent = null;
|
Group parent = null;
|
||||||
if (!string.IsNullOrWhiteSpace(parentname))
|
if (!string.IsNullOrWhiteSpace(parentname))
|
||||||
{
|
{
|
||||||
parent = groups.FirstOrDefault(gp => gp.Name == parentname);
|
parent = GetGroupByName(parentname);
|
||||||
if (null == parent)
|
if (parent == null || parent == group)
|
||||||
throw new GroupManagerException("Invalid parent {0} for group {1}".SFormat(parentname, name));
|
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
|
// Ensure any group validation is also persisted to the DB.
|
||||||
var newgroup = new Group(name, parent, chatcolor, permissions);
|
var newGroup = new Group(name, parent, chatcolor, permissions);
|
||||||
string query = "UPDATE GroupList SET Parent=@0, Commands=@1, ChatColor=@2 WHERE GroupName=@3";
|
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)
|
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 + "'");
|
throw new GroupManagerException(string.Format("Failed to update group \"{0}\".", name));
|
||||||
|
|
||||||
Group group = TShock.Utils.GetGroup(name);
|
|
||||||
group.ChatColor = chatcolor;
|
group.ChatColor = chatcolor;
|
||||||
group.Permissions = permissions;
|
group.Permissions = permissions;
|
||||||
group.Parent = TShock.Utils.GetGroup(parentname);
|
group.Parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMPAT_SIGS
|
#if COMPAT_SIGS
|
||||||
|
|
@ -252,53 +282,106 @@ namespace TShockAPI.DB
|
||||||
|
|
||||||
public void LoadPermisions()
|
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
|
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"))
|
using (var reader = database.QueryReader("SELECT * FROM GroupList"))
|
||||||
{
|
{
|
||||||
while (reader.Read())
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
var group = new Group(reader.Get<String>("GroupName"), null, reader.Get<String>("ChatColor"), reader.Get<String>("Commands"));
|
string groupName = reader.Get<string>("GroupName");
|
||||||
group.Prefix = reader.Get<String>("Prefix");
|
if (groupName == "superadmin")
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
group.Parent = parent.Item1;
|
|
||||||
}
|
}
|
||||||
tempgroups.Add(group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
groups.Clear();
|
try
|
||||||
groups.AddRange(tempgroups);
|
{
|
||||||
|
// 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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error(ex.ToString());
|
Log.ConsoleError("Error on reloading groups: " + ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml;
|
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
using Terraria;
|
using Terraria;
|
||||||
|
|
||||||
|
|
@ -238,25 +236,21 @@ namespace TShockAPI.DB
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Region top = null;
|
Region top = null;
|
||||||
for (int i = 0; i < Regions.Count; i++)
|
|
||||||
{
|
foreach (Region region in Regions.ToList())
|
||||||
if (Regions[i].InArea(x,y) )
|
{
|
||||||
{
|
if (region.InArea(x, y))
|
||||||
if (top == null)
|
{
|
||||||
top = Regions[i];
|
if (top == null || region.Z > top.Z)
|
||||||
else
|
top = region;
|
||||||
{
|
}
|
||||||
if (Regions[i].Z > top.Z)
|
}
|
||||||
top = Regions[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return top == null || top.HasPermissionToBuildInRegion(ply);
|
return top == null || top.HasPermissionToBuildInRegion(ply);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool InArea(int x, int y)
|
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 &&
|
if (x >= region.Area.Left && x <= region.Area.Right &&
|
||||||
y >= region.Area.Top && y <= region.Area.Bottom &&
|
y >= region.Area.Top && y <= region.Area.Bottom &&
|
||||||
|
|
@ -271,7 +265,7 @@ namespace TShockAPI.DB
|
||||||
public List<string> InAreaRegionName(int x, int y)
|
public List<string> InAreaRegionName(int x, int y)
|
||||||
{
|
{
|
||||||
List<string> regions = new List<string>() { };
|
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 &&
|
if (x >= region.Area.Left && x <= region.Area.Right &&
|
||||||
y >= region.Area.Top && y <= region.Area.Bottom &&
|
y >= region.Area.Top && y <= region.Area.Bottom &&
|
||||||
|
|
@ -286,7 +280,7 @@ namespace TShockAPI.DB
|
||||||
public List<Region> InAreaRegion(int x, int y)
|
public List<Region> InAreaRegion(int x, int y)
|
||||||
{
|
{
|
||||||
List<Region> regions = new List<Region>() { };
|
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 &&
|
if (x >= region.Area.Left && x <= region.Area.Right &&
|
||||||
y >= region.Area.Top && y <= region.Area.Bottom &&
|
y >= region.Area.Top && y <= region.Area.Bottom &&
|
||||||
|
|
@ -385,30 +379,36 @@ namespace TShockAPI.DB
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AddNewUser(string regionName, String userName)
|
public bool AddNewUser(string regionName, string userName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string MergedIDs = string.Empty;
|
string mergedIDs = string.Empty;
|
||||||
using (
|
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()))
|
Main.worldID.ToString()))
|
||||||
{
|
{
|
||||||
if (reader.Read())
|
if (reader.Read())
|
||||||
MergedIDs = reader.Get<string>("UserIds");
|
mergedIDs = reader.Get<string>("UserIds");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(MergedIDs))
|
string userIdToAdd = Convert.ToString(TShock.Users.GetUserID(userName));
|
||||||
MergedIDs = Convert.ToString(TShock.Users.GetUserID(userName));
|
string[] ids = mergedIDs.Split(',');
|
||||||
else
|
// Is the user already allowed to the region?
|
||||||
MergedIDs = MergedIDs + "," + Convert.ToString(TShock.Users.GetUserID(userName));
|
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());
|
regionName, Main.worldID.ToString());
|
||||||
foreach (var r in Regions)
|
foreach (var r in Regions)
|
||||||
{
|
{
|
||||||
if (r.Name == regionName && r.WorldID == Main.worldID.ToString())
|
if (r.Name == regionName && r.WorldID == Main.worldID.ToString())
|
||||||
r.setAllowedIDs(MergedIDs);
|
r.setAllowedIDs(mergedIDs);
|
||||||
}
|
}
|
||||||
return q != 0;
|
return q != 0;
|
||||||
}
|
}
|
||||||
|
|
@ -471,27 +471,33 @@ namespace TShockAPI.DB
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AllowGroup(string regionName, string groups)
|
public bool AllowGroup(string regionName, string groupName)
|
||||||
{
|
{
|
||||||
string groupsNew = "";
|
string mergedGroups = "";
|
||||||
using (
|
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()))
|
Main.worldID.ToString()))
|
||||||
{
|
{
|
||||||
if (reader.Read())
|
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());
|
regionName, Main.worldID.ToString());
|
||||||
|
|
||||||
Region r = GetRegionByName(regionName);
|
Region r = GetRegionByName(regionName);
|
||||||
if (r != null)
|
if (r != null)
|
||||||
{
|
{
|
||||||
r.SetAllowedGroups(groupsNew);
|
r.SetAllowedGroups(mergedGroups);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
|
@ -112,7 +113,7 @@ namespace TShockAPI.DB
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ((X != 0) && ( Y !=0)) //invalid pos!
|
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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
namespace TShockAPI.DB
|
namespace TShockAPI.DB
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
|
@ -38,7 +38,8 @@ namespace TShockAPI.DB
|
||||||
new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true},
|
new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true},
|
||||||
new SqlColumn("Password", MySqlDbType.VarChar, 128),
|
new SqlColumn("Password", MySqlDbType.VarChar, 128),
|
||||||
new SqlColumn("Usergroup", MySqlDbType.Text),
|
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,
|
var creator = new SqlTableCreator(db,
|
||||||
db.GetSqlType() == SqlType.Sqlite
|
db.GetSqlType() == SqlType.Sqlite
|
||||||
|
|
@ -59,8 +60,8 @@ namespace TShockAPI.DB
|
||||||
int ret;
|
int ret;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ret = database.Query("INSERT INTO Users (Username, Password, UserGroup, IP) VALUES (@0, @1, @2, @3);", user.Name,
|
ret = database.Query("INSERT INTO Users (Username, Password, UserGroup) VALUES (@0, @1, @2);", user.Name,
|
||||||
TShock.Utils.HashPassword(user.Password), user.Group, user.Address);
|
TShock.Utils.HashPassword(user.Password), user.Group);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -82,18 +83,10 @@ namespace TShockAPI.DB
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int affected = -1;
|
int affected = database.Query("DELETE FROM Users WHERE Username=@0", user.Name);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (affected < 1)
|
if (affected < 1)
|
||||||
throw new UserNotExistException(string.IsNullOrEmpty(user.Address) ? user.Name : user.Address);
|
throw new UserNotExistException(user.Name);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -101,7 +94,6 @@ namespace TShockAPI.DB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the Hashed Password for a given username
|
/// Sets the Hashed Password for a given username
|
||||||
/// </summary>
|
/// </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)
|
public int GetUserID(string username)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -169,53 +174,6 @@ namespace TShockAPI.DB
|
||||||
return -1;
|
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)
|
public User GetUserByName(string name)
|
||||||
{
|
{
|
||||||
try
|
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)
|
public User GetUser(User user)
|
||||||
{
|
{
|
||||||
bool multiple = false;
|
bool multiple = false;
|
||||||
|
|
@ -264,18 +210,12 @@ namespace TShockAPI.DB
|
||||||
arg = user.ID;
|
arg = user.ID;
|
||||||
type = "id";
|
type = "id";
|
||||||
}
|
}
|
||||||
else if (string.IsNullOrEmpty(user.Address))
|
else
|
||||||
{
|
{
|
||||||
query = "SELECT * FROM Users WHERE Username=@0";
|
query = "SELECT * FROM Users WHERE Username=@0";
|
||||||
arg = user.Name;
|
arg = user.Name;
|
||||||
type = "name";
|
type = "name";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
query = "SELECT * FROM Users WHERE IP=@0";
|
|
||||||
arg = user.Address;
|
|
||||||
type = "ip";
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -298,7 +238,7 @@ namespace TShockAPI.DB
|
||||||
if (multiple)
|
if (multiple)
|
||||||
throw new UserManagerException(String.Format("Multiple users found for {0} '{1}'", type, arg));
|
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()
|
public List<User> GetUsers()
|
||||||
|
|
@ -328,7 +268,8 @@ namespace TShockAPI.DB
|
||||||
user.Group = result.Get<string>("Usergroup");
|
user.Group = result.Get<string>("Usergroup");
|
||||||
user.Password = result.Get<string>("Password");
|
user.Password = result.Get<string>("Password");
|
||||||
user.Name = result.Get<string>("Username");
|
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;
|
return user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -339,22 +280,25 @@ namespace TShockAPI.DB
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
public string Group { 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;
|
Name = name;
|
||||||
Password = pass;
|
Password = pass;
|
||||||
Group = group;
|
Group = group;
|
||||||
|
LastAccessed = last;
|
||||||
|
KnownIps = known;
|
||||||
}
|
}
|
||||||
|
|
||||||
public User()
|
public User()
|
||||||
{
|
{
|
||||||
Address = "";
|
|
||||||
Name = "";
|
Name = "";
|
||||||
Password = "";
|
Password = "";
|
||||||
Group = "";
|
Group = "";
|
||||||
|
LastAccessed = "";
|
||||||
|
KnownIps = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
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.
|
* Copyright (C) 2008 MaxMind, Inc. All Rights Reserved.
|
||||||
*
|
*
|
||||||
|
|
@ -16,24 +34,6 @@
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Streams;
|
using System.IO.Streams;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using TShockAPI.DB;
|
||||||
using Terraria;
|
using Terraria;
|
||||||
using TShockAPI.Net;
|
using TShockAPI.Net;
|
||||||
|
|
||||||
|
|
@ -86,13 +89,18 @@ namespace TShockAPI
|
||||||
/// Did the tile get destroyed successfully.
|
/// Did the tile get destroyed successfully.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Fail { get; set; }
|
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>
|
/// <summary>
|
||||||
/// TileEdit - called when a tile is placed or destroyed
|
/// TileEdit - called when a tile is placed or destroyed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static HandlerList<TileEditEventArgs> TileEdit;
|
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)
|
if (TileEdit == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -104,7 +112,8 @@ namespace TShockAPI
|
||||||
Y = y,
|
Y = y,
|
||||||
Type = type,
|
Type = type,
|
||||||
EditType = editType,
|
EditType = editType,
|
||||||
Fail = fail
|
Fail = fail,
|
||||||
|
Style = style
|
||||||
};
|
};
|
||||||
TileEdit.Invoke(null, args);
|
TileEdit.Invoke(null, args);
|
||||||
return args.Handled;
|
return args.Handled;
|
||||||
|
|
@ -1189,6 +1198,14 @@ namespace TShockAPI
|
||||||
byte prefix = args.Data.ReadInt8();
|
byte prefix = args.Data.ReadInt8();
|
||||||
short type = args.Data.ReadInt16();
|
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))
|
if (OnPlayerSlot(plr, slot, stack, prefix, type))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
@ -1202,6 +1219,7 @@ namespace TShockAPI
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Garabage? Or will it cause some internal initialization or whatever?
|
||||||
var item = new Item();
|
var item = new Item();
|
||||||
item.netDefaults(type);
|
item.netDefaults(type);
|
||||||
item.Prefix(prefix);
|
item.Prefix(prefix);
|
||||||
|
|
@ -1210,6 +1228,13 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
args.Player.PlayerData.StoreSlot(slot, type, prefix, stack);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1226,7 +1251,7 @@ namespace TShockAPI
|
||||||
if (args.Player.FirstMaxHP == 0)
|
if (args.Player.FirstMaxHP == 0)
|
||||||
args.Player.FirstMaxHP = max;
|
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);
|
TShock.Utils.ForceKick(args.Player, "Hacked Client Detected.", true);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1252,7 +1277,7 @@ namespace TShockAPI
|
||||||
if (args.Player.FirstMaxMP == 0)
|
if (args.Player.FirstMaxMP == 0)
|
||||||
args.Player.FirstMaxMP = max;
|
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);
|
TShock.Utils.ForceKick(args.Player, "Hacked Client Detected.", true);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1281,12 +1306,6 @@ namespace TShockAPI
|
||||||
TShock.Utils.ForceKick(args.Player, "Empty Name.", true);
|
TShock.Utils.ForceKick(args.Player, "Empty Name.", true);
|
||||||
return 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)
|
if (args.Player.ReceivedInfo)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1336,6 +1355,10 @@ namespace TShockAPI
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
string password = Encoding.UTF8.GetString(args.Data.ReadBytes((int) (args.Data.Length - args.Data.Position - 1)));
|
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);
|
var user = TShock.Users.GetUserByName(args.Player.Name);
|
||||||
if (user != null && !TShock.Config.DisableLoginBeforeJoin)
|
if (user != null && !TShock.Config.DisableLoginBeforeJoin)
|
||||||
{
|
{
|
||||||
|
|
@ -1359,11 +1382,13 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
else if (!TShock.CheckInventory(args.Player))
|
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.SendMessage("Login Failed, Please fix the above errors then /login again.", Color.Cyan);
|
||||||
args.Player.IgnoreActionsForClearingTrashCan = true;
|
args.Player.IgnoreActionsForClearingTrashCan = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
args.Player.LoginFailsBySsi = false;
|
||||||
|
|
||||||
if (group.HasPermission(Permissions.ignorestackhackdetection))
|
if (group.HasPermission(Permissions.ignorestackhackdetection))
|
||||||
args.Player.IgnoreActionsForCheating = "none";
|
args.Player.IgnoreActionsForCheating = "none";
|
||||||
|
|
@ -1372,6 +1397,7 @@ namespace TShockAPI
|
||||||
args.Player.IgnoreActionsForDisabledArmor = "none";
|
args.Player.IgnoreActionsForDisabledArmor = "none";
|
||||||
|
|
||||||
args.Player.Group = group;
|
args.Player.Group = group;
|
||||||
|
args.Player.tempGroup = null;
|
||||||
args.Player.UserAccountName = args.Player.Name;
|
args.Player.UserAccountName = args.Player.Name;
|
||||||
args.Player.UserID = TShock.Users.GetUserID(args.Player.UserAccountName);
|
args.Player.UserID = TShock.Users.GetUserID(args.Player.UserAccountName);
|
||||||
args.Player.IsLoggedIn = true;
|
args.Player.IsLoggedIn = true;
|
||||||
|
|
@ -1384,7 +1410,7 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
args.Player.SendMessage("Authenticated as " + args.Player.Name + " successfully.", Color.LimeGreen);
|
args.Player.SendMessage("Authenticated as " + args.Player.Name + " successfully.", Color.LimeGreen);
|
||||||
Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user " + args.Player.Name + ".");
|
Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user " + args.Player.Name + ".");
|
||||||
Hooks.PlayerLoginEvent.OnPlayerLogin(args.Player);
|
Hooks.PlayerHooks.OnPlayerPostLogin(args.Player);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
TShock.Utils.ForceKick(args.Player, "Invalid user account password.", 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);
|
TShock.Utils.ForceKick(args.Player, "Blank name.", true);
|
||||||
return 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);
|
TShock.Utils.ForceKick(args.Player, "You have hacked health/mana, please use a different character.", true);
|
||||||
return 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,
|
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(),
|
args.Player.Group.Name, args.Player.Country, TShock.Utils.ActivePlayers(),
|
||||||
TShock.Config.MaxSlots));
|
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
|
else
|
||||||
{
|
{
|
||||||
Log.Info(string.Format("{0} ({1}) from '{2}' group joined. ({3}/{4})", args.Player.Name, args.Player.IP,
|
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));
|
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)
|
if (TShock.Config.DisplayIPToAdmins)
|
||||||
|
|
@ -1651,10 +1679,12 @@ namespace TShockAPI
|
||||||
var tileX = args.Data.ReadInt32();
|
var tileX = args.Data.ReadInt32();
|
||||||
var tileY = args.Data.ReadInt32();
|
var tileY = args.Data.ReadInt32();
|
||||||
var tiletype = args.Data.ReadInt8();
|
var tiletype = args.Data.ReadInt8();
|
||||||
var fail = args.Data.ReadBoolean();
|
var fail = tiletype == 1;
|
||||||
if (OnTileEdit(args.Player, tileX, tileY, tiletype, type, fail))
|
var style = args.Data.ReadInt8();
|
||||||
|
|
||||||
|
if (OnTileEdit(args.Player, tileX, tileY, tiletype, type, fail, style))
|
||||||
return true;
|
return true;
|
||||||
if (!TShock.Utils.TileValid(tileX, tileY))
|
if (!TShock.Utils.TilePlacementValid(tileX, tileY))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (args.Player.Dead && TShock.Config.PreventDeadModification)
|
if (args.Player.Dead && TShock.Config.PreventDeadModification)
|
||||||
|
|
@ -1662,18 +1692,63 @@ namespace TShockAPI
|
||||||
|
|
||||||
if (args.Player.AwaitingName)
|
if (args.Player.AwaitingName)
|
||||||
{
|
{
|
||||||
var protectedregions = TShock.Regions.InAreaRegionName(tileX, tileY);
|
Debug.Assert(args.Player.AwaitingNameParameters != null);
|
||||||
if (protectedregions.Count == 0)
|
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
string regionlist = string.Join(",", protectedregions.ToArray());
|
if (includeUnprotected)
|
||||||
args.Player.SendMessage("Region Name(s): " + regionlist, Color.Yellow);
|
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.SendTileSquare(tileX, tileY);
|
||||||
args.Player.AwaitingName = false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1687,22 +1762,63 @@ namespace TShockAPI
|
||||||
return true;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
if (type == 1 && (tiletype == 29 || tiletype == 97) && TShock.Config.ServerSideInventory && TShock.Config.DisablePiggybanksOnSSI)
|
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.SendMessage("You cannot place this tile because 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.SendTileSquare(tileX, tileY);
|
args.Player.SendTileSquare(tileX, tileY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1710,21 +1826,32 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
if (TShock.Utils.MaxChests())
|
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);
|
args.Player.SendTileSquare(tileX, tileY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((TShock.Utils.TileValid(tileX, tileY + 1) && Main.tile[tileX, tileY + 1].type == 138) ||
|
if ((TShock.Utils.TilePlacementValid(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))
|
(TShock.Utils.TilePlacementValid(tileX + 1, tileY + 1) && Main.tile[tileX + 1, tileY + 1].type == 138))
|
||||||
{
|
{
|
||||||
args.Player.SendTileSquare(tileX, tileY);
|
args.Player.SendTileSquare(tileX, tileY);
|
||||||
return true;
|
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);
|
args.Player.SendTileSquare(tileX, tileY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -2040,17 +2167,18 @@ namespace TShockAPI
|
||||||
return true;
|
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)
|
if (type == 100)
|
||||||
{ //fix for skele prime
|
{ //fix for skele prime
|
||||||
Log.Debug("Skeletron Prime's death laser ignored for cheat detection..");
|
Log.Debug("Skeletron Prime's death laser ignored for cheat detection..");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
args.Player.Disable("Does not have projectile permission to update projectile.");
|
args.Player.Disable("Does not have projectile permission to update projectile.");
|
||||||
args.Player.RemoveProjectile(ident, owner);
|
args.Player.RemoveProjectile(ident, owner);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2069,14 +2197,22 @@ namespace TShockAPI
|
||||||
|
|
||||||
if (!args.Player.Group.HasPermission(Permissions.ignoreprojectiledetection))
|
if (!args.Player.Group.HasPermission(Permissions.ignoreprojectiledetection))
|
||||||
{
|
{
|
||||||
if ((type ==90) && (TShock.Config.ProjIgnoreShrapnel))// ignore shrapnel
|
if ((type == 90) && (TShock.Config.ProjIgnoreShrapnel))// ignore shrapnel
|
||||||
{
|
{
|
||||||
Log.Debug("Ignoring shrapnel per config..");
|
Log.Debug("Ignoring shrapnel per config..");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
args.Player.ProjectileThreshold++;
|
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;
|
return false;
|
||||||
|
|
@ -2192,18 +2328,36 @@ namespace TShockAPI
|
||||||
bucket = 2;
|
bucket = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lava && bucket != 2 && !args.Player.Group.HasPermission(Permissions.usebanneditem) &&
|
if(lava && bucket != 2)
|
||||||
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.Disable("Spreading lava without holding a lava bucket");
|
||||||
args.Player.SendTileSquare(tileX, tileY);
|
args.Player.SendTileSquare(tileX, tileY);
|
||||||
return true;
|
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) &&
|
if (!lava && bucket != 1)
|
||||||
TShock.Itembans.ItemIsBanned("Water Bucket", args.Player))
|
{
|
||||||
|
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);
|
args.Player.SendTileSquare(tileX, tileY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -2286,7 +2440,7 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
if (TShock.Config.BanOnMediumcoreDeath)
|
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);
|
TShock.Utils.ForceKick(args.Player, "Death results in a ban, but can't ban you.", true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2782,7 +2936,7 @@ namespace TShockAPI
|
||||||
break;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
@ -28,7 +29,7 @@ namespace TShockAPI
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default chat color.
|
/// Default chat color.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string defaultChatColor = "255.255.255";
|
public const string defaultChatColor = "255,255,255";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of permissions available to the group.
|
/// List of permissions available to the group.
|
||||||
|
|
@ -151,6 +152,7 @@ namespace TShockAPI
|
||||||
public byte G = 255;
|
public byte G = 255;
|
||||||
public byte B = 255;
|
public byte B = 255;
|
||||||
|
|
||||||
|
public static Group DefaultGroup = null;
|
||||||
#if COMPAT_SIGS
|
#if COMPAT_SIGS
|
||||||
[Obsolete("This constructor is for signature compatibility for external code only")]
|
[Obsolete("This constructor is for signature compatibility for external code only")]
|
||||||
public Group(string groupname, Group parentgroup, string chatcolor)
|
public Group(string groupname, Group parentgroup, string chatcolor)
|
||||||
|
|
@ -204,7 +206,7 @@ namespace TShockAPI
|
||||||
return true;
|
return true;
|
||||||
if (traversed.Contains(cur))
|
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);
|
traversed.Add(cur);
|
||||||
cur = cur.Parent;
|
cur = cur.Parent;
|
||||||
|
|
@ -271,6 +273,26 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
permissions.Remove(permission);
|
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>
|
/// <summary>
|
||||||
|
|
@ -298,4 +320,4 @@ namespace TShockAPI
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace TShockAPI
|
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
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
@ -72,6 +73,16 @@ namespace TShockAPI
|
||||||
Write(message, LogLevel.Data);
|
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>
|
/// <summary>
|
||||||
/// Writes an error to the log file.
|
/// Writes an error to the log file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -81,6 +92,16 @@ namespace TShockAPI
|
||||||
Write(message, LogLevel.Error);
|
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>
|
/// <summary>
|
||||||
/// Writes an error to the log file.
|
/// Writes an error to the log file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -93,6 +114,16 @@ namespace TShockAPI
|
||||||
Write(message, LogLevel.Error);
|
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>
|
/// <summary>
|
||||||
/// Writes a warning to the log file.
|
/// Writes a warning to the log file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -102,6 +133,16 @@ namespace TShockAPI
|
||||||
Write(message, LogLevel.Warning);
|
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>
|
/// <summary>
|
||||||
/// Writes an informative string to the log file.
|
/// Writes an informative string to the log file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -111,6 +152,16 @@ namespace TShockAPI
|
||||||
Write(message, LogLevel.Info);
|
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>
|
/// <summary>
|
||||||
/// Writes an informative string to the log file. Also outputs to the console.
|
/// Writes an informative string to the log file. Also outputs to the console.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -123,6 +174,16 @@ namespace TShockAPI
|
||||||
Write(message, LogLevel.Info);
|
Write(message, LogLevel.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes an informative string to the log file. Also outputs to the console.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="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>
|
/// <summary>
|
||||||
/// Writes a debug string to the log file.
|
/// Writes a debug string to the log file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -132,6 +193,16 @@ namespace TShockAPI
|
||||||
Write(message, LogLevel.Debug);
|
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>
|
/// <summary>
|
||||||
/// Disposes objects that are being used.
|
/// Disposes objects that are being used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Streams;
|
using System.IO.Streams;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Streams;
|
using System.IO.Streams;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Streams;
|
using System.IO.Streams;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Streams;
|
using System.IO.Streams;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Streams;
|
using System.IO.Streams;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Streams;
|
using System.IO.Streams;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
@ -121,24 +122,24 @@ namespace TShockAPI
|
||||||
|
|
||||||
public bool Flush(ServerSock socket)
|
public bool Flush(ServerSock socket)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (socket == null || !socket.active)
|
if (socket == null || !socket.active)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (buffers[socket.whoAmI].Count < 1)
|
if (buffers[socket.whoAmI].Count < 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
byte[] buff = buffers[socket.whoAmI].GetBytes(BytesPerUpdate);
|
byte[] buff = buffers[socket.whoAmI].GetBytes(BytesPerUpdate);
|
||||||
if (buff == null)
|
if (buff == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (SendBytes(socket, buff))
|
if (SendBytes(socket, buff))
|
||||||
{
|
{
|
||||||
buffers[socket.whoAmI].Pop(buff.Length);
|
buffers[socket.whoAmI].Pop(buff.Length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.ConsoleError(e.ToString());
|
Log.ConsoleError(e.ToString());
|
||||||
|
|
@ -200,7 +201,14 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
catch (SocketException e)
|
catch (SocketException e)
|
||||||
{
|
{
|
||||||
Log.Warn(e.ToString());
|
switch ((uint)e.ErrorCode)
|
||||||
|
{
|
||||||
|
case 0x80004005:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.Warn(e.ToString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
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
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
@ -26,161 +27,258 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
public static class Permissions
|
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
|
[Description("User can ban others.")]
|
||||||
ignorekilltiledetection;
|
public static readonly string ban = "tshock.admin.ban";
|
||||||
|
|
||||||
[Description("Prevents you from being reverted by place tile abuse detection")] public static readonly string
|
[Description("User can manage warps.")]
|
||||||
ignoreplacetiledetection;
|
public static readonly string managewarp = "tshock.admin.warp";
|
||||||
|
|
||||||
[Description("Prevents you from being disabled by liquid set abuse detection")] public static readonly string
|
[Description("User can manage item bans.")]
|
||||||
ignoreliquidsetdetection;
|
public static readonly string manageitem = "tshock.admin.itemban";
|
||||||
|
|
||||||
[Description("Prevents you from being disabled by liquid set abuse detection")] public static readonly string
|
[Description("User can manage groups.")]
|
||||||
ignoreprojectiledetection;
|
public static readonly string managegroup = "tshock.admin.group";
|
||||||
|
|
||||||
[Description("Prevents you from being reverted by no clip detection")] public static readonly string
|
[Description("User can manage regions.")]
|
||||||
ignorenoclipdetection;
|
public static readonly string manageregion = "tshock.admin.region";
|
||||||
|
|
||||||
[Description("Prevents you from being disabled by stack hack detection")] public static readonly string
|
[Description("User can mute and unmute users")]
|
||||||
ignorestackhackdetection;
|
public static readonly string mute = "tshock.admin.mute";
|
||||||
|
|
||||||
[Description("Prevents you from being kicked by hacked health detection")] public static readonly string
|
[Description("User can see the id of players with /who")]
|
||||||
ignorestathackdetection;
|
public static readonly string seeids = "tshock.admin.seeplayerids";
|
||||||
|
|
||||||
[Description("Prevents your actions from being ignored if damage is too high")] public static readonly string
|
[Description("User can save all the players SSI state.")]
|
||||||
ignoredamagecap;
|
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
|
[Description("User can broadcast messages.")]
|
||||||
reservedslot;
|
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
|
[Description("Users can stop people from teleporting to them")]
|
||||||
string allowclientsideworldedit;
|
public static readonly string tpallow = "tshock.tp.block";
|
||||||
|
|
||||||
[Description("User can summon bosses using items")]
|
[Description("Users can tp to anyone")]
|
||||||
public static readonly string summonboss;
|
public static readonly string tpall = "tshock.tp.toall";
|
||||||
|
|
||||||
[Description("User can start invasions (Goblin/Snow Legion) using items")]
|
[Description("Users can tp to people without showing a notice")]
|
||||||
public static readonly string startinvasion;
|
public static readonly string tphide = "tshock.tp.silent";
|
||||||
|
|
||||||
[Description("User can see the id of players with /who")]
|
[Description("User can use /home.")]
|
||||||
public static readonly string seeids;
|
public static readonly string home = "tshock.tp.home";
|
||||||
|
|
||||||
[Description("User can save all the players SSI state.")]
|
[Description("User can use /spawn.")]
|
||||||
public static readonly string savessi;
|
public static readonly string spawn = "tshock.tp.spawn";
|
||||||
|
|
||||||
[Description("User can use rest api calls.")]
|
// tshock.world nodes
|
||||||
public static readonly string restapi;
|
|
||||||
|
|
||||||
[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()
|
[Description("User can set the time.")]
|
||||||
{
|
public static readonly string time = "tshock.world.settime";
|
||||||
foreach (var field in typeof (Permissions).GetFields())
|
|
||||||
{
|
|
||||||
field.SetValue(null, field.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Backwards compatability.
|
[Description("User can grow plants.")]
|
||||||
restapi = "api";
|
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>
|
/// <summary>
|
||||||
/// Lists all commands associated with a given permission
|
/// Lists all commands associated with a given permission
|
||||||
|
|
@ -191,7 +289,7 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
if (Commands.ChatCommands.Count < 1)
|
if (Commands.ChatCommands.Count < 1)
|
||||||
Commands.InitCommands();
|
Commands.InitCommands();
|
||||||
return Commands.ChatCommands.Where(c => c.Permission == perm).ToList();
|
return Commands.ChatCommands.Where(c => c.Permissions.Contains(perm)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
@ -25,9 +26,9 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTitle("TShock for Terraria")]
|
[assembly: AssemblyTitle("TShock for Terraria")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("Nyx Team")]
|
[assembly: AssemblyCompany("Nyx Studios & TShock Contributors")]
|
||||||
[assembly: AssemblyProduct("TShockAPI")]
|
[assembly: AssemblyProduct("TShockAPI")]
|
||||||
[assembly: AssemblyCopyright("Copyright © Nyx Team 2012")]
|
[assembly: AssemblyCopyright("Copyright © Nyx Studios 2011-2013")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
|
@ -48,5 +49,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// MMdd of the build
|
// MMdd of the build
|
||||||
|
|
||||||
[assembly: AssemblyVersion("4.0.0.0923")]
|
[assembly: AssemblyVersion("4.1.0.0926")]
|
||||||
[assembly: AssemblyFileVersion("4.0.0.0923")]
|
[assembly: AssemblyFileVersion("4.1.0.0926")]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
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
|
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
|
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
|
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 {
|
namespace TShockAPI {
|
||||||
using System;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
@ -38,6 +39,15 @@ namespace Rests
|
||||||
/// <returns>Response object or null to not handle request</returns>
|
/// <returns>Response object or null to not handle request</returns>
|
||||||
public delegate object RestCommandD(RestVerbs verbs, IParameterCollection parameters);
|
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
|
public class Rest : IDisposable
|
||||||
{
|
{
|
||||||
private readonly List<RestCommand> commands = new List<RestCommand>();
|
private readonly List<RestCommand> commands = new List<RestCommand>();
|
||||||
|
|
@ -170,24 +180,47 @@ namespace Rests
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
return new Dictionary<string, string>
|
return new RestObject("500")
|
||||||
{
|
{
|
||||||
{"status", "500"},
|
|
||||||
{"error", "Internal server error."},
|
{"error", "Internal server error."},
|
||||||
{"errormsg", exception.Message},
|
{"errormsg", exception.Message},
|
||||||
{"stacktrace", exception.StackTrace},
|
{"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."}
|
{"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)
|
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
|
#region Dispose
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using HttpServer;
|
||||||
|
|
||||||
namespace Rests
|
namespace Rests
|
||||||
{
|
{
|
||||||
|
|
@ -26,8 +28,10 @@ namespace Rests
|
||||||
public string UriTemplate { get; protected set; }
|
public string UriTemplate { get; protected set; }
|
||||||
public string UriVerbMatch { get; protected set; }
|
public string UriVerbMatch { get; protected set; }
|
||||||
public string[] UriVerbs { get; protected set; }
|
public string[] UriVerbs { get; protected set; }
|
||||||
public RestCommandD Callback { get; protected set; }
|
public virtual bool RequiresToken { get { return false; } }
|
||||||
public bool RequiresToken { get; set; }
|
public bool DoLog { get; set; }
|
||||||
|
|
||||||
|
private RestCommandD callback;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
@ -42,8 +46,8 @@ namespace Rests
|
||||||
UriVerbMatch = string.Format("^{0}$", string.Join("([^/]*)", Regex.Split(uritemplate, "\\{[^\\{\\}]*\\}")));
|
UriVerbMatch = string.Format("^{0}$", string.Join("([^/]*)", Regex.Split(uritemplate, "\\{[^\\{\\}]*\\}")));
|
||||||
var matches = Regex.Matches(uritemplate, "\\{([^\\{\\}]*)\\}");
|
var matches = Regex.Matches(uritemplate, "\\{([^\\{\\}]*)\\}");
|
||||||
UriVerbs = (from Match match in matches select match.Groups[1].Value).ToArray();
|
UriVerbs = (from Match match in matches select match.Groups[1].Value).ToArray();
|
||||||
Callback = callback;
|
this.callback = callback;
|
||||||
RequiresToken = true;
|
DoLog = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -60,5 +64,43 @@ namespace Rests
|
||||||
{
|
{
|
||||||
get { return UriVerbs.Length > 0; }
|
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
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using HttpServer;
|
using HttpServer;
|
||||||
using Rests;
|
using Rests;
|
||||||
|
|
@ -38,78 +40,140 @@ namespace TShockAPI
|
||||||
public void RegisterRestfulCommands()
|
public void RegisterRestfulCommands()
|
||||||
{
|
{
|
||||||
// Server Commands
|
// Server Commands
|
||||||
Rest.Register(new RestCommand("/v2/server/broadcast", ServerBroadcast));
|
if (TShock.Config.EnableTokenEndpointAuthentication)
|
||||||
Rest.Register(new RestCommand("/v2/server/off", ServerOff));
|
{
|
||||||
Rest.Register(new RestCommand("/v2/server/rawcmd", ServerCommand));
|
Rest.Register(new SecureRestCommand("/v2/server/status", ServerStatusV2));
|
||||||
Rest.Register(new RestCommand("/v2/server/status", ServerStatusV2) { RequiresToken = false });
|
Rest.Register(new SecureRestCommand("/status", ServerStatus));
|
||||||
Rest.Register(new RestCommand("/tokentest", ServerTokenTest));
|
Rest.Register(new SecureRestCommand("/v3/server/motd", ServerMotd));
|
||||||
Rest.Register(new RestCommand("/status", ServerStatus) { RequiresToken = false });
|
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
|
// User Commands
|
||||||
Rest.Register(new RestCommand("/v2/users/activelist", UserActiveListV2));
|
Rest.Register(new SecureRestCommand("/v2/users/activelist", UserActiveListV2, RestPermissions.restviewusers));
|
||||||
Rest.Register(new RestCommand("/v2/users/create", UserCreateV2));
|
Rest.Register(new SecureRestCommand("/v2/users/create", UserCreateV2, RestPermissions.restmanageusers) { DoLog = false });
|
||||||
Rest.Register(new RestCommand("/v2/users/list", UserListV2));
|
Rest.Register(new SecureRestCommand("/v2/users/list", UserListV2, RestPermissions.restviewusers));
|
||||||
Rest.Register(new RestCommand("/v2/users/read", UserInfoV2));
|
Rest.Register(new SecureRestCommand("/v2/users/read", UserInfoV2, RestPermissions.restviewusers));
|
||||||
Rest.Register(new RestCommand("/v2/users/destroy", UserDestroyV2));
|
Rest.Register(new SecureRestCommand("/v2/users/destroy", UserDestroyV2, RestPermissions.restmanageusers));
|
||||||
Rest.Register(new RestCommand("/v2/users/update", UserUpdateV2));
|
Rest.Register(new SecureRestCommand("/v2/users/update", UserUpdateV2, RestPermissions.restmanageusers) { DoLog = false });
|
||||||
|
|
||||||
// Ban Commands
|
// Ban Commands
|
||||||
Rest.Register(new RestCommand("/bans/create", BanCreate));
|
Rest.Register(new SecureRestCommand("/bans/create", BanCreate, RestPermissions.restmanagebans));
|
||||||
Rest.Register(new RestCommand("/v2/bans/list", BanListV2));
|
Rest.Register(new SecureRestCommand("/v2/bans/list", BanListV2, RestPermissions.restviewbans));
|
||||||
Rest.Register(new RestCommand("/v2/bans/read", BanInfoV2));
|
Rest.Register(new SecureRestCommand("/v2/bans/read", BanInfoV2, RestPermissions.restviewbans));
|
||||||
Rest.Register(new RestCommand("/v2/bans/destroy", BanDestroyV2));
|
Rest.Register(new SecureRestCommand("/v2/bans/destroy", BanDestroyV2, RestPermissions.restmanagebans));
|
||||||
|
|
||||||
// World Commands
|
// World Commands
|
||||||
Rest.Register(new RestCommand("/world/read", WorldRead));
|
Rest.Register(new SecureRestCommand("/world/read", WorldRead));
|
||||||
Rest.Register(new RestCommand("/world/meteor", WorldMeteor));
|
Rest.Register(new SecureRestCommand("/world/meteor", WorldMeteor, RestPermissions.restcauseevents));
|
||||||
Rest.Register(new RestCommand("/world/bloodmoon/{bool}", WorldBloodmoon));
|
Rest.Register(new SecureRestCommand("/world/bloodmoon/{bool}", WorldBloodmoon, RestPermissions.restcauseevents));
|
||||||
Rest.Register(new RestCommand("/v2/world/save", WorldSave));
|
Rest.Register(new SecureRestCommand("/v2/world/save", WorldSave, RestPermissions.restcfg));
|
||||||
Rest.Register(new RestCommand("/v2/world/autosave/state/{bool}", WorldChangeSaveSettings));
|
Rest.Register(new SecureRestCommand("/v2/world/autosave/state/{bool}", WorldChangeSaveSettings, RestPermissions.restcfg));
|
||||||
Rest.Register(new RestCommand("/v2/world/butcher", WorldButcher));
|
Rest.Register(new SecureRestCommand("/v2/world/butcher", WorldButcher, RestPermissions.restbutcher));
|
||||||
|
|
||||||
// Player Commands
|
// Player Commands
|
||||||
Rest.Register(new RestCommand("/lists/players", PlayerList));
|
Rest.Register(new SecureRestCommand("/lists/players", PlayerList));
|
||||||
Rest.Register(new RestCommand("/v2/players/list", PlayerListV2));
|
Rest.Register(new SecureRestCommand("/v2/players/list", PlayerListV2));
|
||||||
Rest.Register(new RestCommand("/v2/players/read", PlayerReadV2));
|
Rest.Register(new SecureRestCommand("/v2/players/read", PlayerReadV2, RestPermissions.restuserinfo));
|
||||||
Rest.Register(new RestCommand("/v2/players/kick", PlayerKickV2));
|
Rest.Register(new SecureRestCommand("/v2/players/kick", PlayerKickV2, RestPermissions.restkick));
|
||||||
Rest.Register(new RestCommand("/v2/players/ban", PlayerBanV2));
|
Rest.Register(new SecureRestCommand("/v2/players/ban", PlayerBanV2, RestPermissions.restban, RestPermissions.restmanagebans));
|
||||||
Rest.Register(new RestCommand("/v2/players/kill", PlayerKill));
|
Rest.Register(new SecureRestCommand("/v2/players/kill", PlayerKill, RestPermissions.restkill));
|
||||||
Rest.Register(new RestCommand("/v2/players/mute", PlayerMute));
|
Rest.Register(new SecureRestCommand("/v2/players/mute", PlayerMute, RestPermissions.restmute));
|
||||||
Rest.Register(new RestCommand("/v2/players/unmute", PlayerUnMute));
|
Rest.Register(new SecureRestCommand("/v2/players/unmute", PlayerUnMute, RestPermissions.restmute));
|
||||||
|
|
||||||
// Group Commands
|
// Group Commands
|
||||||
Rest.Register(new RestCommand("/v2/groups/list", GroupList));
|
Rest.Register(new SecureRestCommand("/v2/groups/list", GroupList, RestPermissions.restviewgroups));
|
||||||
Rest.Register(new RestCommand("/v2/groups/read", GroupInfo));
|
Rest.Register(new SecureRestCommand("/v2/groups/read", GroupInfo, RestPermissions.restviewgroups));
|
||||||
Rest.Register(new RestCommand("/v2/groups/destroy", GroupDestroy));
|
Rest.Register(new SecureRestCommand("/v2/groups/destroy", GroupDestroy, RestPermissions.restmanagegroups));
|
||||||
Rest.Register(new RestCommand("/v2/groups/create", GroupCreate));
|
Rest.Register(new SecureRestCommand("/v2/groups/create", GroupCreate, RestPermissions.restmanagegroups));
|
||||||
Rest.Register(new RestCommand("/v2/groups/update", GroupUpdate));
|
Rest.Register(new SecureRestCommand("/v2/groups/update", GroupUpdate, RestPermissions.restmanagegroups));
|
||||||
}
|
}
|
||||||
|
|
||||||
#region RestServerMethods
|
#region RestServerMethods
|
||||||
|
|
||||||
private object ServerCommand(RestVerbs verbs, IParameterCollection parameters)
|
private object ServerCommand(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(parameters["cmd"]))
|
if (string.IsNullOrWhiteSpace(parameters["cmd"]))
|
||||||
return RestMissingParam("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"]);
|
Commands.HandleCommand(tr, parameters["cmd"]);
|
||||||
return RestResponse(string.Join("\n", tr.GetCommandOutput()));
|
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))
|
if (!GetBool(parameters["confirm"], false))
|
||||||
return RestInvalidParam("confirm");
|
return RestInvalidParam("confirm");
|
||||||
|
|
||||||
// Inform players the server is shutting down
|
// Inform players the server is shutting down
|
||||||
var msg = string.IsNullOrWhiteSpace(parameters["message"]) ? "Server is shutting down" : parameters["message"];
|
var reason = string.IsNullOrWhiteSpace(parameters["message"]) ? "Server is shutting down" : parameters["message"];
|
||||||
TShock.Utils.StopServer(!GetBool(parameters["nosave"], false), msg);
|
TShock.Utils.StopServer(!GetBool(parameters["nosave"], false), reason);
|
||||||
|
|
||||||
return RestResponse("The server is shutting down");
|
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"];
|
var msg = parameters["msg"];
|
||||||
if (string.IsNullOrWhiteSpace(msg))
|
if (string.IsNullOrWhiteSpace(msg))
|
||||||
|
|
@ -118,11 +182,32 @@ namespace TShockAPI
|
||||||
return RestResponse("The message was broadcasted successfully");
|
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)
|
string motdFilePath = Path.Combine(TShock.SavePath, "motd.txt");
|
||||||
return RestError("Server settings require a token for this API call");
|
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();
|
var activeplayers = Main.player.Where(p => null != p && p.active).ToList();
|
||||||
return new RestObject()
|
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()
|
var ret = new RestObject()
|
||||||
{
|
{
|
||||||
{"name", TShock.Config.ServerName},
|
{"name", TShock.Config.ServerName},
|
||||||
{"port", TShock.Config.ServerPort},
|
{"port", TShock.Config.ServerPort},
|
||||||
{"playercount", Main.player.Where(p => null != p && p.active).Count()},
|
{"playercount", Main.player.Where(p => null != p && p.active).Count()},
|
||||||
{"maxplayers", TShock.Config.MaxSlots},
|
{"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))
|
if (GetBool(parameters["players"], false))
|
||||||
|
|
@ -174,52 +258,56 @@ namespace TShockAPI
|
||||||
rules.Add("PvPMode", TShock.Config.PvPMode);
|
rules.Add("PvPMode", TShock.Config.PvPMode);
|
||||||
rules.Add("SpawnProtection", TShock.Config.SpawnProtection);
|
rules.Add("SpawnProtection", TShock.Config.SpawnProtection);
|
||||||
rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius);
|
rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius);
|
||||||
|
rules.Add("ServerSideInventory", TShock.Config.ServerSideInventory);
|
||||||
|
|
||||||
ret.Add("rules", rules);
|
ret.Add("rules", rules);
|
||||||
}
|
}
|
||||||
return ret;
|
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
|
#endregion
|
||||||
|
|
||||||
#region RestUserMethods
|
#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)) } };
|
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>(){
|
return new RestObject() { { "users", TShock.Users.GetUsers().Select(p => new Dictionary<string,object>(){
|
||||||
{"name", p.Name},
|
{"name", p.Name},
|
||||||
{"id", p.ID},
|
{"id", p.ID},
|
||||||
{"group", p.Group},
|
{"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"];
|
var username = parameters["user"];
|
||||||
if (string.IsNullOrWhiteSpace(username))
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
return RestMissingParam("user");
|
return RestMissingParam("user");
|
||||||
|
|
||||||
var group = parameters["group"];
|
var group = parameters["group"];
|
||||||
if (string.IsNullOrWhiteSpace(group))
|
if (string.IsNullOrWhiteSpace(group))
|
||||||
return RestMissingParam("group");
|
group = TShock.Config.DefaultRegistrationGroupName;
|
||||||
|
|
||||||
var password = parameters["password"];
|
var password = parameters["password"];
|
||||||
if (string.IsNullOrWhiteSpace(password))
|
if (string.IsNullOrWhiteSpace(password))
|
||||||
return RestMissingParam("password");
|
return RestMissingParam("password");
|
||||||
|
|
||||||
// NOTE: ip can be blank
|
// NOTE: ip can be blank
|
||||||
User user = new User(parameters["ip"], username, password, group);
|
User user = new User(username, password, group, "", "");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TShock.Users.AddUser(user);
|
TShock.Users.AddUser(user);
|
||||||
|
|
@ -232,7 +320,7 @@ namespace TShockAPI
|
||||||
return RestResponse("User was successfully created");
|
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);
|
var ret = UserFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -274,7 +362,7 @@ namespace TShockAPI
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
private object UserDestroyV2(RestVerbs verbs, IParameterCollection parameters)
|
private object UserDestroyV2(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||||
{
|
{
|
||||||
var ret = UserFind(parameters);
|
var ret = UserFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -292,7 +380,7 @@ namespace TShockAPI
|
||||||
return RestResponse("User deleted successfully");
|
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);
|
var ret = UserFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -306,7 +394,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
#region RestBanMethods
|
#region RestBanMethods
|
||||||
|
|
||||||
private object BanCreate(RestVerbs verbs, IParameterCollection parameters)
|
private object BanCreate(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||||
{
|
{
|
||||||
var ip = parameters["ip"];
|
var ip = parameters["ip"];
|
||||||
var name = parameters["name"];
|
var name = parameters["name"];
|
||||||
|
|
@ -316,7 +404,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TShock.Bans.AddBan(ip, name, parameters["reason"], true);
|
TShock.Bans.AddBan(ip, name, parameters["reason"], true, tokenData.Username);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
@ -325,7 +413,7 @@ namespace TShockAPI
|
||||||
return RestResponse("Ban created successfully");
|
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);
|
var ret = BanFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -357,7 +445,7 @@ namespace TShockAPI
|
||||||
return RestResponse("Ban deleted successfully");
|
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);
|
var ret = BanFind(parameters);
|
||||||
if (ret is RestObject)
|
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();
|
var banList = new ArrayList();
|
||||||
foreach (var ban in TShock.Bans.GetBans())
|
foreach (var ban in TShock.Bans.GetBans())
|
||||||
|
|
@ -393,7 +481,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
#region RestWorldMethods
|
#region RestWorldMethods
|
||||||
|
|
||||||
private object WorldChangeSaveSettings(RestVerbs verbs, IParameterCollection parameters)
|
private object WorldChangeSaveSettings(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||||
{
|
{
|
||||||
bool autoSave;
|
bool autoSave;
|
||||||
if (!bool.TryParse(verbs["bool"], out autoSave))
|
if (!bool.TryParse(verbs["bool"], out autoSave))
|
||||||
|
|
@ -403,14 +491,14 @@ namespace TShockAPI
|
||||||
return RestResponse("AutoSave has been set to " + autoSave);
|
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();
|
SaveManager.Instance.SaveWorld();
|
||||||
|
|
||||||
return RestResponse("World saved");
|
return RestResponse("World saved");
|
||||||
}
|
}
|
||||||
|
|
||||||
private object WorldButcher(RestVerbs verbs, IParameterCollection parameters)
|
private object WorldButcher(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||||
{
|
{
|
||||||
bool killFriendly;
|
bool killFriendly;
|
||||||
if (!bool.TryParse(parameters["killfriendly"], out killFriendly))
|
if (!bool.TryParse(parameters["killfriendly"], out killFriendly))
|
||||||
|
|
@ -432,7 +520,7 @@ namespace TShockAPI
|
||||||
return RestResponse(killcount + " NPCs have been killed");
|
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()
|
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)
|
if (null == WorldGen.genRand)
|
||||||
WorldGen.genRand = new Random();
|
WorldGen.genRand = new Random();
|
||||||
|
|
@ -453,7 +541,7 @@ namespace TShockAPI
|
||||||
return RestResponse("Meteor has been spawned");
|
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;
|
bool bloodmoon;
|
||||||
if (!bool.TryParse(verbs["bool"], out bloodmoon))
|
if (!bool.TryParse(verbs["bool"], out bloodmoon))
|
||||||
|
|
@ -467,23 +555,23 @@ namespace TShockAPI
|
||||||
|
|
||||||
#region RestPlayerMethods
|
#region RestPlayerMethods
|
||||||
|
|
||||||
private object PlayerUnMute(RestVerbs verbs, IParameterCollection parameters)
|
private object PlayerUnMute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||||
{
|
{
|
||||||
return PlayerSetMute(parameters, false);
|
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);
|
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();
|
var activeplayers = Main.player.Where(p => null != p && p.active).ToList();
|
||||||
return new RestObject() { { "players", string.Join(", ", activeplayers.Select(p => p.name)) } };
|
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();
|
var playerList = new ArrayList();
|
||||||
foreach (TSPlayer tsPlayer in TShock.Players.Where(p => null != p))
|
foreach (TSPlayer tsPlayer in TShock.Players.Where(p => null != p))
|
||||||
|
|
@ -495,7 +583,7 @@ namespace TShockAPI
|
||||||
return new RestObject() { { "players", playerList } };
|
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);
|
var ret = PlayerFind(parameters);
|
||||||
if (ret is RestObject)
|
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);
|
var ret = PlayerFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -526,7 +614,7 @@ namespace TShockAPI
|
||||||
return RestResponse("Player " + player.Name + " was kicked");
|
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);
|
var ret = PlayerFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -539,7 +627,7 @@ namespace TShockAPI
|
||||||
return RestResponse("Player " + player.Name + " was banned");
|
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);
|
var ret = PlayerFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -556,7 +644,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
#region RestGroupMethods
|
#region RestGroupMethods
|
||||||
|
|
||||||
private object GroupList(RestVerbs verbs, IParameterCollection parameters)
|
private object GroupList(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||||
{
|
{
|
||||||
var groups = new ArrayList();
|
var groups = new ArrayList();
|
||||||
foreach (Group group in TShock.Groups)
|
foreach (Group group in TShock.Groups)
|
||||||
|
|
@ -566,7 +654,7 @@ namespace TShockAPI
|
||||||
return new RestObject() { { "groups", groups } };
|
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);
|
var ret = GroupFind(parameters);
|
||||||
if (ret is RestObject)
|
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);
|
var ret = GroupFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -602,7 +690,7 @@ namespace TShockAPI
|
||||||
return RestResponse("Group '" + group.Name + "' deleted successfully");
|
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"];
|
var name = parameters["group"];
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
|
@ -619,7 +707,7 @@ namespace TShockAPI
|
||||||
return RestResponse("Group '" + name + "' created successfully");
|
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);
|
var ret = GroupFind(parameters);
|
||||||
if (ret is RestObject)
|
if (ret is RestObject)
|
||||||
|
|
@ -713,10 +801,6 @@ namespace TShockAPI
|
||||||
break;
|
break;
|
||||||
case "id":
|
case "id":
|
||||||
user = TShock.Users.GetUserByID(Convert.ToInt32(name));
|
user = TShock.Users.GetUserByID(Convert.ToInt32(name));
|
||||||
break;
|
|
||||||
case "ip":
|
|
||||||
user = TShock.Users.GetUserByIP(name);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return RestError("Invalid Type: '" + type + "'");
|
return RestError("Invalid Type: '" + type + "'");
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
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
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using HttpServer;
|
using HttpServer;
|
||||||
|
using TShockAPI;
|
||||||
|
using TShockAPI.DB;
|
||||||
|
|
||||||
namespace Rests
|
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 class SecureRest : Rest
|
||||||
{
|
{
|
||||||
public Dictionary<string, object> Tokens { get; protected set; }
|
public struct TokenData
|
||||||
public event VerifyD Verify;
|
{
|
||||||
|
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)
|
public SecureRest(IPAddress ip, int port)
|
||||||
: base(ip, port)
|
: base(ip, port)
|
||||||
{
|
{
|
||||||
Tokens = new Dictionary<string, object>();
|
Tokens = new Dictionary<string, TokenData>();
|
||||||
Register(new RestCommand("/token/create/{username}/{password}", NewToken) {RequiresToken = false});
|
AppTokens = new Dictionary<string, TokenData>();
|
||||||
Register(new RestCommand("/v2/token/create/{password}", NewTokenV2) { RequiresToken = false });
|
|
||||||
Register(new RestCommand("/token/destroy/{token}", DestroyToken) {RequiresToken = true});
|
Register(new RestCommand("/token/create/{username}/{password}", NewToken) { DoLog = false });
|
||||||
foreach (KeyValuePair<string, string> t in TShockAPI.TShock.RESTStartupTokens)
|
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"];
|
var token = verbs["token"];
|
||||||
try
|
try
|
||||||
|
|
@ -58,11 +93,19 @@ namespace Rests
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
return new Dictionary<string, string>
|
return new RestObject("400")
|
||||||
{{"status", "400"}, {"error", "The specified token queued for destruction failed to be deleted."}};
|
{ Error = "The specified token queued for destruction failed to be deleted." };
|
||||||
}
|
}
|
||||||
return new Dictionary<string, string>
|
return new RestObject()
|
||||||
{{"status", "200"}, {"response", "Requested token was successfully destroyed."}};
|
{ 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)
|
private object NewTokenV2(RestVerbs verbs, IParameterCollection parameters)
|
||||||
|
|
@ -70,29 +113,7 @@ namespace Rests
|
||||||
var user = parameters["username"];
|
var user = parameters["username"];
|
||||||
var pass = verbs["password"];
|
var pass = verbs["password"];
|
||||||
|
|
||||||
RestObject obj = null;
|
return this.NewTokenInternal(user, pass);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private object NewToken(RestVerbs verbs, IParameterCollection parameters)
|
private object NewToken(RestVerbs verbs, IParameterCollection parameters)
|
||||||
|
|
@ -100,55 +121,83 @@ namespace Rests
|
||||||
var user = verbs["username"];
|
var user = verbs["username"];
|
||||||
var pass = verbs["password"];
|
var pass = verbs["password"];
|
||||||
|
|
||||||
RestObject obj = null;
|
RestObject response = this.NewTokenInternal(user, pass);
|
||||||
if (Verify != null)
|
response["deprecated"] = "This endpoint is depracted and will be removed in the future.";
|
||||||
obj = Verify(user, pass);
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj == null)
|
private RestObject NewTokenInternal(string username, string password)
|
||||||
obj = new RestObject("401")
|
{
|
||||||
{Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair."};
|
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)
|
Group userGroup = TShock.Utils.GetGroup(userAccount.Group);
|
||||||
return obj;
|
if (!userGroup.HasPermission(RestPermissions.restapi) && userAccount.Group != "superadmin")
|
||||||
|
return new RestObject("403")
|
||||||
string hash;
|
{ 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 rand = new Random();
|
||||||
var randbytes = new byte[32];
|
var randbytes = new byte[32];
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
rand.NextBytes(randbytes);
|
rand.NextBytes(randbytes);
|
||||||
hash = randbytes.Aggregate("", (s, b) => s + b.ToString("X2"));
|
tokenHash = randbytes.Aggregate("", (s, b) => s + b.ToString("X2"));
|
||||||
} while (Tokens.ContainsKey(hash));
|
} while (Tokens.ContainsKey(tokenHash));
|
||||||
|
|
||||||
Tokens.Add(hash, user);
|
Tokens.Add(tokenHash, new TokenData { Username = userAccount.Name, UserGroupName = userGroup.Name });
|
||||||
|
|
||||||
obj["token"] = hash;
|
RestObject response = new RestObject() { Response = "Successful login" };
|
||||||
obj["deprecated"] = "This method will be removed from TShock in 3.6.";
|
response["token"] = tokenHash;
|
||||||
return obj;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
||||||
{
|
{
|
||||||
if (cmd.RequiresToken)
|
if (!cmd.RequiresToken)
|
||||||
{
|
return base.ExecuteCommand(cmd, verbs, parms);
|
||||||
var strtoken = parms["token"];
|
|
||||||
if (strtoken == null)
|
var token = parms["token"];
|
||||||
return new Dictionary<string, string>
|
if (token == null)
|
||||||
{{"status", "401"}, {"error", "Not authorized. The specified API endpoint requires a token."}};
|
return new RestObject("401")
|
||||||
|
{ Error = "Not authorized. The specified API endpoint requires a token." };
|
||||||
|
|
||||||
object token;
|
SecureRestCommand secureCmd = (SecureRestCommand)cmd;
|
||||||
if (!Tokens.TryGetValue(strtoken, out token))
|
TokenData tokenData;
|
||||||
return new Dictionary<string, string>
|
if (!Tokens.TryGetValue(token, out tokenData) && !AppTokens.TryGetValue(token, out tokenData))
|
||||||
{
|
return new RestObject("403")
|
||||||
{"status", "403"},
|
{ Error = "Not authorized. The specified API endpoint requires a token, but the provided token was not valid." };
|
||||||
{
|
|
||||||
"error",
|
// TODO: Get rid of this when the old REST permission model is removed.
|
||||||
"Not authorized. The specified API endpoint requires a token, but the provided token was not valid."
|
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.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Diagnostics;
|
|
||||||
using Terraria;
|
using Terraria;
|
||||||
|
|
||||||
namespace TShockAPI
|
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
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
@ -71,10 +72,26 @@ namespace TShockAPI
|
||||||
|
|
||||||
public int FirstMaxMP { get; set; }
|
public int FirstMaxMP { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The player's group.
|
/// The player's group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Group Group { get; set; }
|
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; }
|
public bool ReceivedInfo { get; set; }
|
||||||
|
|
||||||
|
|
@ -105,6 +122,8 @@ namespace TShockAPI
|
||||||
|
|
||||||
public bool AwaitingName { get; set; }
|
public bool AwaitingName { get; set; }
|
||||||
|
|
||||||
|
public string[] AwaitingNameParameters { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The last time a player broke a grief check.
|
/// The last time a player broke a grief check.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -144,15 +163,21 @@ namespace TShockAPI
|
||||||
public string UserAccountName { get; set; }
|
public string UserAccountName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public bool HasBeenSpammedWithBuildMessage;
|
public bool LoginFailsBySsi { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the player is logged in or not.
|
/// Whether the player is logged in or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsLoggedIn;
|
public bool IsLoggedIn;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the player has sent their whole inventory to the server while connecting.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasSentInventory { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The player's user id( from the db ).
|
/// The player's user id( from the db ).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -215,6 +240,8 @@ namespace TShockAPI
|
||||||
|
|
||||||
public bool SilentKickInProgress;
|
public bool SilentKickInProgress;
|
||||||
|
|
||||||
|
public bool SilentJoinInProgress;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of points where ice tiles have been placed.
|
/// A list of points where ice tiles have been placed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -381,7 +408,7 @@ namespace TShockAPI
|
||||||
TilesDestroyed = new Dictionary<Vector2, TileData>();
|
TilesDestroyed = new Dictionary<Vector2, TileData>();
|
||||||
TilesCreated = new Dictionary<Vector2, TileData>();
|
TilesCreated = new Dictionary<Vector2, TileData>();
|
||||||
Index = index;
|
Index = index;
|
||||||
Group = new Group(TShock.Config.DefaultGuestGroupName);
|
Group = Group.DefaultGroup;
|
||||||
IceTiles = new List<Point>();
|
IceTiles = new List<Point>();
|
||||||
AwaitingResponse = new Dictionary<string, Action<object>>();
|
AwaitingResponse = new Dictionary<string, Action<object>>();
|
||||||
}
|
}
|
||||||
|
|
@ -392,7 +419,7 @@ namespace TShockAPI
|
||||||
TilesCreated = new Dictionary<Vector2, TileData>();
|
TilesCreated = new Dictionary<Vector2, TileData>();
|
||||||
Index = -1;
|
Index = -1;
|
||||||
FakePlayer = new Player {name = playerName, whoAmi = -1};
|
FakePlayer = new Player {name = playerName, whoAmi = -1};
|
||||||
Group = new Group(TShock.Config.DefaultGuestGroupName);
|
Group = Group.DefaultGroup;
|
||||||
AwaitingResponse = new Dictionary<string, Action<object>>();
|
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)
|
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;
|
return false;
|
||||||
|
|
||||||
GiveItem(type,name,width,height,stack,prefix);
|
GiveItem(type,name,width,height,stack,prefix);
|
||||||
|
|
@ -585,21 +613,41 @@ namespace TShockAPI
|
||||||
SendMessage(msg, Color.Yellow);
|
SendMessage(msg, Color.Yellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendInfoMessage(string format, params object[] args)
|
||||||
|
{
|
||||||
|
SendInfoMessage(string.Format(format, args));
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void SendSuccessMessage(string msg)
|
public virtual void SendSuccessMessage(string msg)
|
||||||
{
|
{
|
||||||
SendMessage(msg, Color.Green);
|
SendMessage(msg, Color.Green);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendSuccessMessage(string format, params object[] args)
|
||||||
|
{
|
||||||
|
SendSuccessMessage(string.Format(format, args));
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void SendWarningMessage(string msg)
|
public virtual void SendWarningMessage(string msg)
|
||||||
{
|
{
|
||||||
SendMessage(msg, Color.OrangeRed);
|
SendMessage(msg, Color.OrangeRed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendWarningMessage(string format, params object[] args)
|
||||||
|
{
|
||||||
|
SendWarningMessage(string.Format(format, args));
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void SendErrorMessage(string msg)
|
public virtual void SendErrorMessage(string msg)
|
||||||
{
|
{
|
||||||
SendMessage(msg, Color.Red);
|
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.")]
|
[Obsolete("Use SendErrorMessage, SendInfoMessage, or SendWarningMessage, or a custom color instead.")]
|
||||||
public virtual void SendMessage(string msg)
|
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();
|
Group = playerGroup;
|
||||||
AwaitingResponse = new Dictionary<string, Action<object>>();
|
AwaitingResponse = new Dictionary<string, Action<object>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SendMessage(string msg)
|
public override void SendMessage(string msg)
|
||||||
|
|
@ -734,21 +782,43 @@ namespace TShockAPI
|
||||||
|
|
||||||
public override void SendMessage(string msg, byte red, byte green, byte blue)
|
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()
|
public List<string> GetCommandOutput()
|
||||||
{
|
{
|
||||||
return CommandReturn;
|
return this.CommandOutput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TSServerPlayer : TSPlayer
|
public class TSServerPlayer : TSPlayer
|
||||||
{
|
{
|
||||||
|
public static string AccountName = "ServerConsole";
|
||||||
public TSServerPlayer()
|
public TSServerPlayer()
|
||||||
: base("Server")
|
: base("Server")
|
||||||
{
|
{
|
||||||
Group = new SuperAdminGroup();
|
Group = new SuperAdminGroup();
|
||||||
|
UserAccountName = AccountName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SendErrorMessage(string msg)
|
public override void SendErrorMessage(string msg)
|
||||||
|
|
@ -832,6 +902,10 @@ namespace TShockAPI
|
||||||
|
|
||||||
public void StrikeNPC(int npcid, int damage, float knockBack, int hitDirection)
|
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);
|
Main.npc[npcid].StrikeNPC(damage, knockBack, hitDirection);
|
||||||
NetMessage.SendData((int) PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
|
NetMessage.SendData((int) PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
@ -23,13 +24,14 @@ using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
|
||||||
using Hooks;
|
using Hooks;
|
||||||
using MaxMind;
|
using MaxMind;
|
||||||
using Mono.Data.Sqlite;
|
using Mono.Data.Sqlite;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Rests;
|
using Rests;
|
||||||
using Terraria;
|
using Terraria;
|
||||||
using TShockAPI.DB;
|
using TShockAPI.DB;
|
||||||
|
|
@ -37,16 +39,18 @@ using TShockAPI.Net;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
{
|
{
|
||||||
[APIVersion(1, 12)]
|
[APIVersion(1, 13)]
|
||||||
public class TShock : TerrariaPlugin
|
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 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";
|
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 TSPlayer[] Players = new TSPlayer[Main.maxPlayers];
|
||||||
public static BanManager Bans;
|
public static BanManager Bans;
|
||||||
|
|
@ -66,11 +70,10 @@ namespace TShockAPI
|
||||||
public static SecureRest RestApi;
|
public static SecureRest RestApi;
|
||||||
public static RestManager RestManager;
|
public static RestManager RestManager;
|
||||||
public static Utils Utils = Utils.Instance;
|
public static Utils Utils = Utils.Instance;
|
||||||
public static StatTracker StatTracker = new StatTracker();
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for implementing REST Tokens prior to the REST system starting up.
|
/// Used for implementing REST Tokens prior to the REST system starting up.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Dictionary<string, string> RESTStartupTokens = new Dictionary<string, string>();
|
public static Dictionary<string, SecureRest.TokenData> RESTStartupTokens = new Dictionary<string, SecureRest.TokenData>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called after TShock is initialized. Useful for plugins that needs hooks before tshock but also depend on tshock being loaded.
|
/// 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."; }
|
get { return "The administration modification of the future."; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string UpdateURL
|
||||||
|
{
|
||||||
|
get { return ""; }
|
||||||
|
}
|
||||||
public TShock(Main game)
|
public TShock(Main game)
|
||||||
: base(game)
|
: base(game)
|
||||||
{
|
{
|
||||||
|
|
@ -108,35 +115,57 @@ namespace TShockAPI
|
||||||
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
HandleCommandLine(Environment.GetCommandLineArgs());
|
|
||||||
|
|
||||||
if (!Directory.Exists(SavePath))
|
|
||||||
Directory.CreateDirectory(SavePath);
|
|
||||||
|
|
||||||
DateTime now = DateTime.Now;
|
|
||||||
string logFilename;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
logFilename = Path.Combine(SavePath, now.ToString(LogFormat)+".log");
|
HandleCommandLine(Environment.GetCommandLineArgs());
|
||||||
}
|
|
||||||
catch(Exception)
|
if (Version.Major >= 4)
|
||||||
{
|
getTShockAscii();
|
||||||
// Problem with the log format use the default
|
|
||||||
logFilename = Path.Combine(SavePath, now.ToString(LogFormatDefault) + ".log");
|
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
|
#if DEBUG
|
||||||
Log.Initialize(logFilename, LogLevel.All, false);
|
Log.Initialize(logFilename, LogLevel.All, false);
|
||||||
#else
|
#else
|
||||||
Log.Initialize(logFilename, LogLevel.All & ~LogLevel.Debug, LogClear);
|
Log.Initialize(logFilename, LogLevel.All & ~LogLevel.Debug, LogClear);
|
||||||
#endif
|
#endif
|
||||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
if (logPathSetupWarning != null)
|
||||||
|
Log.Warn(logPathSetupWarning);
|
||||||
if (Version.Major >= 4)
|
|
||||||
{
|
|
||||||
getTShockAscii();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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
|
try
|
||||||
{
|
{
|
||||||
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
|
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));
|
File.WriteAllText(Path.Combine(SavePath, "tshock.pid"), Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
ConfigFile.ConfigRead += OnConfigRead;
|
|
||||||
FileTools.SetupConfig();
|
|
||||||
|
|
||||||
HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs());
|
HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs());
|
||||||
|
|
||||||
if (Config.StorageType.ToLower() == "sqlite")
|
if (Config.StorageType.ToLower() == "sqlite")
|
||||||
|
|
@ -195,7 +221,6 @@ namespace TShockAPI
|
||||||
RememberedPos = new RememberedPosManager(DB);
|
RememberedPos = new RememberedPosManager(DB);
|
||||||
InventoryDB = new InventoryManager(DB);
|
InventoryDB = new InventoryManager(DB);
|
||||||
RestApi = new SecureRest(Netplay.serverListenIP, Config.RestApiPort);
|
RestApi = new SecureRest(Netplay.serverListenIP, Config.RestApiPort);
|
||||||
RestApi.Verify += RestApi_Verify;
|
|
||||||
RestApi.Port = Config.RestApiPort;
|
RestApi.Port = Config.RestApiPort;
|
||||||
RestManager = new RestManager(RestApi);
|
RestManager = new RestManager(RestApi);
|
||||||
RestManager.RegisterRestfulCommands();
|
RestManager.RegisterRestfulCommands();
|
||||||
|
|
@ -225,6 +250,7 @@ namespace TShockAPI
|
||||||
WorldHooks.SaveWorld += SaveManager.Instance.OnSaveWorld;
|
WorldHooks.SaveWorld += SaveManager.Instance.OnSaveWorld;
|
||||||
WorldHooks.ChristmasCheck += OnXmasCheck;
|
WorldHooks.ChristmasCheck += OnXmasCheck;
|
||||||
NetHooks.NameCollision += NetHooks_NameCollision;
|
NetHooks.NameCollision += NetHooks_NameCollision;
|
||||||
|
TShockAPI.Hooks.PlayerHooks.PlayerPostLogin += OnPlayerLogin;
|
||||||
|
|
||||||
GetDataHandlers.InitGetDataHandler();
|
GetDataHandlers.InitGetDataHandler();
|
||||||
Commands.InitCommands();
|
Commands.InitCommands();
|
||||||
|
|
@ -269,33 +295,6 @@ namespace TShockAPI
|
||||||
// ReSharper restore LocalizableElement
|
// 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)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
|
@ -326,6 +325,7 @@ namespace TShockAPI
|
||||||
WorldHooks.SaveWorld -= SaveManager.Instance.OnSaveWorld;
|
WorldHooks.SaveWorld -= SaveManager.Instance.OnSaveWorld;
|
||||||
WorldHooks.ChristmasCheck -= OnXmasCheck;
|
WorldHooks.ChristmasCheck -= OnXmasCheck;
|
||||||
NetHooks.NameCollision -= NetHooks_NameCollision;
|
NetHooks.NameCollision -= NetHooks_NameCollision;
|
||||||
|
TShockAPI.Hooks.PlayerHooks.PlayerPostLogin -= OnPlayerLogin;
|
||||||
|
|
||||||
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
|
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
|
||||||
{
|
{
|
||||||
|
|
@ -338,7 +338,31 @@ namespace TShockAPI
|
||||||
base.Dispose(disposing);
|
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());
|
string ip = TShock.Utils.GetRealIP(Netplay.serverSock[who].tcpClient.Client.RemoteEndPoint.ToString());
|
||||||
foreach (TSPlayer ply in TShock.Players)
|
foreach (TSPlayer ply in TShock.Players)
|
||||||
|
|
@ -369,7 +393,7 @@ namespace TShockAPI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnXmasCheck(ChristmasCheckEventArgs args)
|
private void OnXmasCheck(ChristmasCheckEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.Handled)
|
if (args.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
@ -442,9 +466,13 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "-dump":
|
case "-logpath":
|
||||||
ConfigFile.DumpDescriptions();
|
path = parms[++i];
|
||||||
Permissions.DumpDescriptions();
|
if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1)
|
||||||
|
{
|
||||||
|
LogPath = path;
|
||||||
|
Log.ConsoleInfo("Log path has been set to " + path);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "-logformat":
|
case "-logformat":
|
||||||
|
|
@ -454,6 +482,11 @@ namespace TShockAPI
|
||||||
case "-logclear":
|
case "-logclear":
|
||||||
bool.TryParse(parms[++i], out LogClear);
|
bool.TryParse(parms[++i], out LogClear);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "-dump":
|
||||||
|
ConfigFile.DumpDescriptions();
|
||||||
|
Permissions.DumpDescriptions();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -473,7 +506,7 @@ namespace TShockAPI
|
||||||
break;
|
break;
|
||||||
case "-rest-token":
|
case "-rest-token":
|
||||||
string token = Convert.ToString(parms[++i]);
|
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.");
|
Console.WriteLine("Startup parameter overrode REST token.");
|
||||||
break;
|
break;
|
||||||
case "-rest-enabled":
|
case "-rest-enabled":
|
||||||
|
|
@ -537,7 +570,7 @@ namespace TShockAPI
|
||||||
|
|
||||||
Regions.ReloadAllRegions();
|
Regions.ReloadAllRegions();
|
||||||
|
|
||||||
StatTracker.CheckIn();
|
Lighting.lightMode = 2;
|
||||||
FixChestStacks();
|
FixChestStacks();
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -545,6 +578,9 @@ namespace TShockAPI
|
||||||
|
|
||||||
private void FixChestStacks()
|
private void FixChestStacks()
|
||||||
{
|
{
|
||||||
|
if (Config.IgnoreChestStacksOnLoad)
|
||||||
|
return;
|
||||||
|
|
||||||
foreach (Chest chest in Main.chest)
|
foreach (Chest chest in Main.chest)
|
||||||
{
|
{
|
||||||
if (chest != null)
|
if (chest != null)
|
||||||
|
|
@ -564,7 +600,6 @@ namespace TShockAPI
|
||||||
private void OnUpdate()
|
private void OnUpdate()
|
||||||
{
|
{
|
||||||
UpdateManager.UpdateProcedureCheck();
|
UpdateManager.UpdateProcedureCheck();
|
||||||
StatTracker.CheckIn();
|
|
||||||
if (Backups.IsBackupTime)
|
if (Backups.IsBackupTime)
|
||||||
Backups.Backup();
|
Backups.Backup();
|
||||||
//call these every second, not every update
|
//call these every second, not every update
|
||||||
|
|
@ -735,16 +770,8 @@ namespace TShockAPI
|
||||||
private void OnConnect(int ply, HandledEventArgs handler)
|
private void OnConnect(int ply, HandledEventArgs handler)
|
||||||
{
|
{
|
||||||
var player = new TSPlayer(ply);
|
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);
|
Utils.ForceKick(player, Config.ServerFullNoReservedReason, true, false);
|
||||||
handler.Handled = true;
|
handler.Handled = true;
|
||||||
|
|
@ -758,9 +785,14 @@ namespace TShockAPI
|
||||||
|
|
||||||
if (ban != null)
|
if (ban != null)
|
||||||
{
|
{
|
||||||
Utils.ForceKick(player, string.Format("You are banned: {0}", ban.Reason), true, false);
|
if (!Utils.HasBanExpired(ban))
|
||||||
handler.Handled = true;
|
{
|
||||||
return;
|
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))
|
if (!FileTools.OnWhitelist(player.IP))
|
||||||
|
|
@ -811,9 +843,13 @@ namespace TShockAPI
|
||||||
|
|
||||||
if (ban != null)
|
if (ban != null)
|
||||||
{
|
{
|
||||||
Utils.ForceKick(player, string.Format("You are banned: {0}", ban.Reason), true, false);
|
if (!Utils.HasBanExpired(ban))
|
||||||
handler.Handled = true;
|
{
|
||||||
return;
|
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 != 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));
|
Log.Info(string.Format("{0} disconnected.", tsplr.Name));
|
||||||
|
|
||||||
|
|
@ -1451,12 +1484,12 @@ namespace TShockAPI
|
||||||
return (float) Math.Sqrt(num3);
|
return (float) Math.Sqrt(num3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HackedHealth(TSPlayer player)
|
public static bool HackedStats(TSPlayer player)
|
||||||
{
|
{
|
||||||
return (player.TPlayer.statManaMax > 400) ||
|
return (player.TPlayer.statManaMax > TShock.Config.MaxMana) ||
|
||||||
(player.TPlayer.statMana > 400) ||
|
(player.TPlayer.statMana > TShock.Config.MaxMana) ||
|
||||||
(player.TPlayer.statLifeMax > 400) ||
|
(player.TPlayer.statLifeMax > TShock.Config.MaxHealth) ||
|
||||||
(player.TPlayer.statLife > 400);
|
(player.TPlayer.statLife > TShock.Config.MaxHealth);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HackedInventory(TSPlayer player)
|
public static bool HackedInventory(TSPlayer player)
|
||||||
|
|
|
||||||
|
|
@ -61,32 +61,27 @@
|
||||||
<HintPath>..\SqlBins\MySql.Data.dll</HintPath>
|
<HintPath>..\SqlBins\MySql.Data.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</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">
|
<Reference Include="Newtonsoft.Json">
|
||||||
<HintPath>.\Newtonsoft.Json.dll</HintPath>
|
<HintPath>.\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<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.Data" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="TerrariaServer, Version=0.0.0.0, Culture=neutral, processorArchitecture=x86">
|
||||||
<Reference Include="TerrariaServer, Version=1.0.4.0, Culture=neutral, processorArchitecture=x86">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<ExecutableExtension>.exe</ExecutableExtension>
|
<ExecutableExtension>.exe</ExecutableExtension>
|
||||||
<HintPath>..\TerrariaServerBins\TerrariaServer.exe</HintPath>
|
<HintPath>..\TerrariaServerBins\TerrariaServer.exe</HintPath>
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BackupManager.cs" />
|
<Compile Include="BackupManager.cs" />
|
||||||
<Compile Include="DB\RegionManager.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="SaveManager.cs" />
|
||||||
<Compile Include="DB\BanManager.cs" />
|
<Compile Include="DB\BanManager.cs" />
|
||||||
<Compile Include="DB\InventoryManager.cs" />
|
<Compile Include="DB\InventoryManager.cs" />
|
||||||
|
|
@ -131,7 +126,6 @@
|
||||||
<Compile Include="Rest\RestObject.cs" />
|
<Compile Include="Rest\RestObject.cs" />
|
||||||
<Compile Include="Rest\RestVerbs.cs" />
|
<Compile Include="Rest\RestVerbs.cs" />
|
||||||
<Compile Include="Rest\SecureRest.cs" />
|
<Compile Include="Rest\SecureRest.cs" />
|
||||||
<Compile Include="StatTracker.cs" />
|
|
||||||
<Compile Include="Utils.cs" />
|
<Compile Include="Utils.cs" />
|
||||||
<Compile Include="TShock.cs" />
|
<Compile Include="TShock.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
|
@ -185,11 +179,12 @@
|
||||||
</PreBuildEvent>
|
</PreBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>"$(ProjectDir)postbuild.bat"</PostBuildEvent>
|
<PostBuildEvent>
|
||||||
|
</PostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<VisualStudio>
|
<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>
|
</VisualStudio>
|
||||||
</ProjectExtensions>
|
</ProjectExtensions>
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
extensions: .cs
|
extensions: .cs
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
TShock, a server mod for Terraria
|
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
|
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
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
@ -24,6 +25,7 @@ using System.Net.Sockets;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Terraria;
|
using Terraria;
|
||||||
|
using TShockAPI.DB;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
{
|
{
|
||||||
|
|
@ -217,18 +219,19 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends message to all users with 'logs' permission.
|
/// Sends message to all players with 'logs' permission.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="log">Message to send</param>
|
/// <param name="log">Message to send</param>
|
||||||
/// <param name="color">Color of the message</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);
|
Log.Info(log);
|
||||||
TSPlayer.Server.SendMessage(log, color);
|
TSPlayer.Server.SendMessage(log, color);
|
||||||
foreach (TSPlayer player in TShock.Players)
|
foreach (TSPlayer player in TShock.Players)
|
||||||
{
|
{
|
||||||
if (player != null && player.Active && player.Group.HasPermission(Permissions.logs) && player.DisplayLogs &&
|
if (player != null && player != excludedPlayer && player.Active && player.Group.HasPermission(Permissions.logs) &&
|
||||||
TShock.Config.DisableSpewLogs == false)
|
player.DisplayLogs && TShock.Config.DisableSpewLogs == false)
|
||||||
player.SendMessage(log, color);
|
player.SendMessage(log, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -304,7 +307,7 @@ namespace TShockAPI
|
||||||
tileX = startTileX + Random.Next(tileXRange*-1, tileXRange);
|
tileX = startTileX + Random.Next(tileXRange*-1, tileXRange);
|
||||||
tileY = startTileY + Random.Next(tileYRange*-1, tileYRange);
|
tileY = startTileY + Random.Next(tileYRange*-1, tileYRange);
|
||||||
j++;
|
j++;
|
||||||
} while (TileValid(tileX, tileY) && !TileClear(tileX, tileY));
|
} while (TilePlacementValid(tileX, tileY) && !TileClear(tileX, tileY));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -313,7 +316,7 @@ namespace TShockAPI
|
||||||
/// <param name="tileX">Location X</param>
|
/// <param name="tileX">Location X</param>
|
||||||
/// <param name="tileY">Location Y</param>
|
/// <param name="tileY">Location Y</param>
|
||||||
/// <returns>If the tile is valid</returns>
|
/// <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;
|
return tileX >= 0 && tileX < Main.maxTilesX && tileY >= 0 && tileY < Main.maxTilesY;
|
||||||
}
|
}
|
||||||
|
|
@ -560,6 +563,36 @@ namespace TShockAPI
|
||||||
Netplay.disconnect = true;
|
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
|
#if COMPAT_SIGS
|
||||||
[Obsolete("This method is for signature compatibility for external code only")]
|
[Obsolete("This method is for signature compatibility for external code only")]
|
||||||
public void ForceKick(TSPlayer player, string reason)
|
public void ForceKick(TSPlayer player, string reason)
|
||||||
|
|
@ -641,7 +674,7 @@ namespace TShockAPI
|
||||||
{
|
{
|
||||||
string ip = player.IP;
|
string ip = player.IP;
|
||||||
string playerName = player.Name;
|
string playerName = player.Name;
|
||||||
TShock.Bans.AddBan(ip, playerName, reason);
|
TShock.Bans.AddBan(ip, playerName, reason, false, adminUserName);
|
||||||
player.Disconnect(string.Format("Banned: {0}", reason));
|
player.Disconnect(string.Format("Banned: {0}", reason));
|
||||||
Log.ConsoleInfo(string.Format("Banned {0} for : {1}", playerName, reason));
|
Log.ConsoleInfo(string.Format("Banned {0} for : {1}", playerName, reason));
|
||||||
string verb = force ? "force " : "";
|
string verb = force ? "force " : "";
|
||||||
|
|
@ -654,6 +687,29 @@ namespace TShockAPI
|
||||||
return false;
|
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>
|
/// <summary>
|
||||||
/// Shows a file to the user.
|
/// Shows a file to the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -709,7 +765,7 @@ namespace TShockAPI
|
||||||
return TShock.Groups.groups[i];
|
return TShock.Groups.groups[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Group(TShock.Config.DefaultGuestGroupName);
|
return Group.DefaultGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -841,5 +897,25 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
return new string(returnstr);
|
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