Merge pull request #735 from NyxStudios/general-devel
Merge dev to master
This commit is contained in:
commit
2f41b4dd84
50 changed files with 5832 additions and 3546 deletions
|
|
@ -1,9 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = crlf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.cs]
|
||||
indent_style = tab
|
||||
trim_trailing_whitespace = true
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = crlf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.cs]
|
||||
indent_style = tab
|
||||
trim_trailing_whitespace = true
|
||||
|
|
|
|||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "TerrariaServerAPI"]
|
||||
path = TerrariaServerAPI
|
||||
url = https://github.com/Deathmax/TerrariaAPI-Server.git
|
||||
70
CONTRIBUTING
70
CONTRIBUTING
|
|
@ -1,36 +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__.
|
||||
### 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.
|
||||
14
TShock.sln
14
TShock.sln
|
|
@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\Unit
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TShockRestTestPlugin", "TShockRestTestPlugin\TShockRestTestPlugin.csproj", "{F2FEDAFB-58DE-4611-9168-A86112C346C7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerrariaAPI-Server", "TerrariaServerAPI\TerrariaAPI-Server.csproj", "{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(TestCaseManagementSettings) = postSolution
|
||||
CategoryFile = Terraria.vsmdi
|
||||
|
|
@ -52,6 +54,18 @@ Global
|
|||
{F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{F2FEDAFB-58DE-4611-9168-A86112C346C7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Debug|x86.Build.0 = Debug|x86
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Release|x86.ActiveCfg = Release|x86
|
||||
{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
3491
TShockAPI/Commands.cs
Normal file → Executable file
3491
TShockAPI/Commands.cs
Normal file → Executable file
File diff suppressed because it is too large
Load diff
51
TShockAPI/ConfigFile.cs
Normal file → Executable file
51
TShockAPI/ConfigFile.cs
Normal file → Executable file
|
|
@ -80,6 +80,7 @@ namespace TShockAPI
|
|||
[Description("Bans a hardcore player on death.")] public bool BanOnMediumcoreDeath;
|
||||
|
||||
[Description("Enable/disable Terraria's built in auto save.")] public bool AutoSave = true;
|
||||
[Description("Enable/disable save announcements.")] public bool AnnounceSave = true;
|
||||
|
||||
[Description("Number of failed login attempts before kicking the player.")] public int MaximumLoginAttempts = 3;
|
||||
|
||||
|
|
@ -105,6 +106,8 @@ namespace TShockAPI
|
|||
|
||||
[Description("Enables kicking of banned users by matching their IP Address.")] public bool EnableIPBans = true;
|
||||
|
||||
[Description("Enables kicking of banned users by matching their client UUID.")] public bool EnableUUIDBans = true;
|
||||
|
||||
[Description("Enables kicking of banned users by matching their Character Name.")] public bool EnableBanOnUsernames;
|
||||
|
||||
[Description("Selects the default group name to place new registrants under.")] public string
|
||||
|
|
@ -135,8 +138,6 @@ namespace TShockAPI
|
|||
[Description("This will turn on token requirement for the public REST API endpoints.")] public bool
|
||||
EnableTokenEndpointAuthentication;
|
||||
|
||||
[Description("Deprecated. Use ServerName instead.")] public string ServerNickname = "TShock Server";
|
||||
|
||||
[Description("Enable/disable the rest api.")] public bool RestApiEnabled;
|
||||
|
||||
[Description("This is the port which the rest api will listen on.")] public int RestApiPort = 7878;
|
||||
|
|
@ -145,19 +146,15 @@ namespace TShockAPI
|
|||
|
||||
[Description("Displays a player's IP on join to everyone who has the log permission.")] public bool DisplayIPToAdmins;
|
||||
|
||||
[Description(
|
||||
"Some tiles are 'fixed' by not letting TShock handle them. Disabling this may break certain aesthetic tiles.")] public
|
||||
bool EnableInsecureTileFixes = true;
|
||||
|
||||
[Description("Kicks users using a proxy as identified with the GeoIP database.")] public bool KickProxyUsers = true;
|
||||
|
||||
[Description("Disables hardmode, can't never be activated. Overrides /starthardmode.")] public bool DisableHardmode;
|
||||
|
||||
[Description("Disables the dungeon guardian from being spawned by player packets, this will instead force a respawn.")] public bool DisableDungeonGuardian;
|
||||
|
||||
[Description("Enable server side inventory checks, EXPERIMENTAL")] public bool ServerSideInventory;
|
||||
[Description("Enable server side characters, This stops the client from saving character data! EXPERIMENTAL!!!!!")] public bool ServerSideCharacter;
|
||||
|
||||
[Description("How often SSI should save, in minutes.")] public int ServerSideInventorySave = 15;
|
||||
[Description("How often SSC should save, in minutes.")] public int ServerSideCharacterSave = 5;
|
||||
|
||||
[Description("Time, in milliseconds, to disallow discarding items after logging in when ServerSideInventory is ON.")] public int LogonDiscardThreshold=250;
|
||||
|
||||
|
|
@ -169,7 +166,7 @@ namespace TShockAPI
|
|||
"Changes ingame chat format: {0} = Group Name, {1} = Group Prefix, {2} = Player Name, {3} = Group Suffix, {4} = Chat Message"
|
||||
)] public string ChatFormat = "{1}{2}{3}: {4}";
|
||||
|
||||
[Description("Change the chat format when using chat above heads. This begins with a player name wrapped in brackets, as per Terraria's formatting. Same formatting as ChatFormat.")] public string ChatAboveHeadsFormat = "{4}";
|
||||
[Description("Change the player name when using chat above heads. This begins with a player name wrapped in brackets, as per Terraria's formatting. Same formatting as ChatFormat(minus the text aka {4}).")] public string ChatAboveHeadsFormat = "{2}";
|
||||
|
||||
[Description("Force the world time to be normal, day, or night.")] public string ForceTime = "normal";
|
||||
|
||||
|
|
@ -206,6 +203,10 @@ namespace TShockAPI
|
|||
[Description("Disable users from being able to login with account password when joining.")] public bool
|
||||
DisableLoginBeforeJoin;
|
||||
|
||||
[Description("Disable users from being able to login with their client UUID.")] public bool DisableUUIDLogin;
|
||||
|
||||
[Description("Kick clients that don't send a UUID to the server.")] public bool KickEmptyUUID;
|
||||
|
||||
[Description("Allows users to register any username with /register.")] public bool AllowRegisterAnyUsername;
|
||||
|
||||
[Description("Allows users to login with any username with /login.")] public bool AllowLoginAnyUsername = true;
|
||||
|
|
@ -222,7 +223,10 @@ namespace TShockAPI
|
|||
|
||||
[Description("Allow ice placement even when user does not have canbuild.")] public bool AllowIce = false;
|
||||
|
||||
[Description("Allows corrutption to spread when a world is hardmode.")] public bool AllowCorruptionCreep = true;
|
||||
[Description("Allows crimson to spread when a world is hardmode.")]
|
||||
public bool AllowCrimsonCreep = true;
|
||||
|
||||
[Description("Allows corruption to spread when a world is hardmode.")] public bool AllowCorruptionCreep = true;
|
||||
|
||||
[Description("Allows hallow to spread when a world is hardmode.")] public bool AllowHallowCreep = true;
|
||||
|
||||
|
|
@ -234,8 +238,6 @@ namespace TShockAPI
|
|||
|
||||
[Description("Prevent banned items from being /i or /give.")] public bool PreventBannedItemSpawn = false;
|
||||
|
||||
[Description("Prevent banks on SSI.")] public bool DisablePiggybanksOnSSI = false;
|
||||
|
||||
[Description("Prevent players from interacting with the world if dead.")] public bool PreventDeadModification =
|
||||
true;
|
||||
|
||||
|
|
@ -263,11 +265,22 @@ namespace TShockAPI
|
|||
[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 number of reserved slots past your max server slot that can be joined by reserved players")] public int ReservedSlots = 20;
|
||||
|
||||
[Description("The number of reserved slots past your max server slot that can be joined by reserved players")] public bool LogRest = false;
|
||||
|
||||
[Description("The maximum value that a character may have for health.")] public int MaxMana = 400;
|
||||
[Description("The number of seconds a player must wait before being respawned.")] public int RespawnSeconds = 3;
|
||||
|
||||
[Description("Disables a player if this number of tiles is painted within 1 second.")] public int TilePaintThreshold = 15;
|
||||
|
||||
[Description("Enables max packet bufferer size.")] public bool EnableMaxBytesInBuffer = false;
|
||||
|
||||
[Description("Number of bytes in the packet buffer before we disconnect the player.")] public int MaxBytesInBuffer = 5242880;
|
||||
|
||||
[Description("Forces your world to be in Halloween mode regardless of the data.")] public bool ForceHalloween = false;
|
||||
|
||||
[Description("Allows anyone to break grass, pots, etc.")] public bool AllowCutTilesAndBreakables = false;
|
||||
|
||||
[Description("The number of reserved slots past your max server slot that can be joined by reserved players")] public int ReservedSlots = 20;
|
||||
/// <summary>
|
||||
/// Reads a configuration file from a given path
|
||||
/// </summary>
|
||||
|
|
@ -351,10 +364,10 @@ namespace TShockAPI
|
|||
|
||||
var def = field.GetValue(defaults);
|
||||
|
||||
sb.AppendLine("## {0} ".SFormat(name));
|
||||
sb.AppendLine("**Type:** {0} ".SFormat(type));
|
||||
sb.AppendLine("**Description:** {0} ".SFormat(desc));
|
||||
sb.AppendLine("**Default:** \"{0}\" ".SFormat(def));
|
||||
sb.AppendLine("{0} ".SFormat(name));
|
||||
sb.AppendLine("Type: {0} ".SFormat(type));
|
||||
sb.AppendLine("Description: {0} ".SFormat(desc));
|
||||
sb.AppendLine("Default: \"{0}\" ".SFormat(def));
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ namespace TShockAPI.DB
|
|||
var table = new SqlTable("Bans",
|
||||
new SqlColumn("IP", MySqlDbType.String, 16) {Primary = true},
|
||||
new SqlColumn("Name", MySqlDbType.Text),
|
||||
new SqlColumn("UUID", MySqlDbType.Text),
|
||||
new SqlColumn("Reason", MySqlDbType.Text),
|
||||
new SqlColumn("BanningUser", MySqlDbType.Text),
|
||||
new SqlColumn("Date", MySqlDbType.Text),
|
||||
|
|
@ -54,6 +55,11 @@ namespace TShockAPI.DB
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a ban by IP.
|
||||
/// </summary>
|
||||
/// <param name="ip">The IP.</param>
|
||||
/// <returns>The ban.</returns>
|
||||
public Ban GetBanByIp(string ip)
|
||||
{
|
||||
try
|
||||
|
|
@ -61,7 +67,7 @@ namespace TShockAPI.DB
|
|||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE IP=@0", ip))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -71,6 +77,9 @@ namespace TShockAPI.DB
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of bans.
|
||||
/// </summary>
|
||||
public List<Ban> GetBans()
|
||||
{
|
||||
List<Ban> banlist = new List<Ban>();
|
||||
|
|
@ -80,7 +89,7 @@ namespace TShockAPI.DB
|
|||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
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")));
|
||||
banlist.Add(new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration")));
|
||||
}
|
||||
return banlist;
|
||||
}
|
||||
|
|
@ -93,6 +102,12 @@ namespace TShockAPI.DB
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a ban by name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="casesensitive">Whether to check with case sensitivity.</param>
|
||||
/// <returns>The ban.</returns>
|
||||
public Ban GetBanByName(string name, bool casesensitive = true)
|
||||
{
|
||||
try
|
||||
|
|
@ -103,7 +118,29 @@ namespace TShockAPI.DB
|
|||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE " + namecol + "=@0", name))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a ban by UUID.
|
||||
/// </summary>
|
||||
/// <param name="uuid">The UUID.</param>
|
||||
/// <returns>The ban.</returns>
|
||||
public Ban GetBanByUUID(string uuid)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE UUID=@0", uuid))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -117,14 +154,14 @@ namespace TShockAPI.DB
|
|||
[Obsolete("This method is for signature compatibility for external code only")]
|
||||
public bool AddBan(string ip, string name, string reason)
|
||||
{
|
||||
return AddBan(ip, name, reason, false, "", "");
|
||||
return AddBan(ip, name, "", reason, false, "", "");
|
||||
}
|
||||
#endif
|
||||
public bool AddBan(string ip, string name = "", string reason = "", bool exceptions = false, string banner = "", string expiration = "")
|
||||
public bool AddBan(string ip, string name = "", string uuid = "", string reason = "", bool exceptions = false, string banner = "", string expiration = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
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;
|
||||
return database.Query("INSERT INTO Bans (IP, Name, UUID, Reason, BanningUser, Date, Expiration) VALUES (@0, @1, @2, @3, @4, @5, @6);", ip, name, uuid, reason, banner, DateTime.UtcNow.ToString("s"), expiration) != 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -181,6 +218,8 @@ namespace TShockAPI.DB
|
|||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string UUID { get; set; }
|
||||
|
||||
public string Reason { get; set; }
|
||||
|
||||
public string BanningUser { get; set; }
|
||||
|
|
@ -189,10 +228,11 @@ namespace TShockAPI.DB
|
|||
|
||||
public string Expiration { get; set; }
|
||||
|
||||
public Ban(string ip, string name, string reason, string banner, string date, string exp)
|
||||
public Ban(string ip, string name, string uuid, string reason, string banner, string date, string exp)
|
||||
{
|
||||
IP = ip;
|
||||
Name = name;
|
||||
UUID = UUID;
|
||||
Reason = reason;
|
||||
BanningUser = banner;
|
||||
Date = date;
|
||||
|
|
@ -203,6 +243,7 @@ namespace TShockAPI.DB
|
|||
{
|
||||
IP = string.Empty;
|
||||
Name = string.Empty;
|
||||
UUID = string.Empty;
|
||||
Reason = string.Empty;
|
||||
BanningUser = "";
|
||||
Date = "";
|
||||
|
|
|
|||
149
TShockAPI/DB/CharacterManager.cs
Executable file
149
TShockAPI/DB/CharacterManager.cs
Executable file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
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.Data;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
public class CharacterManager
|
||||
{
|
||||
public IDbConnection database;
|
||||
|
||||
public CharacterManager(IDbConnection db)
|
||||
{
|
||||
database = db;
|
||||
|
||||
var table = new SqlTable("tsCharacter",
|
||||
new SqlColumn("Account", MySqlDbType.Int32) {Primary = true},
|
||||
new SqlColumn("Health", MySqlDbType.Int32),
|
||||
new SqlColumn("MaxHealth", MySqlDbType.Int32),
|
||||
new SqlColumn("Mana", MySqlDbType.Int32),
|
||||
new SqlColumn("MaxMana", MySqlDbType.Int32),
|
||||
new SqlColumn("Inventory", MySqlDbType.Text),
|
||||
new SqlColumn("spawnX", MySqlDbType.Int32),
|
||||
new SqlColumn("spawnY", MySqlDbType.Int32)
|
||||
);
|
||||
var creator = new SqlTableCreator(db,
|
||||
db.GetSqlType() == SqlType.Sqlite
|
||||
? (IQueryBuilder) new SqliteQueryCreator()
|
||||
: new MysqlQueryCreator());
|
||||
creator.EnsureExists(table);
|
||||
}
|
||||
|
||||
public PlayerData GetPlayerData(TSPlayer player, int acctid)
|
||||
{
|
||||
PlayerData playerData = new PlayerData(player);
|
||||
|
||||
try
|
||||
{
|
||||
using (var reader = database.QueryReader("SELECT * FROM tsCharacter WHERE Account=@0", acctid))
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
playerData.exists = true;
|
||||
playerData.health = reader.Get<int>("Health");
|
||||
playerData.maxHealth = reader.Get<int>("MaxHealth");
|
||||
playerData.mana = reader.Get<int>("Mana");
|
||||
playerData.maxMana = reader.Get<int>("MaxMana");
|
||||
playerData.inventory = NetItem.Parse(reader.Get<string>("Inventory"));
|
||||
playerData.spawnX = reader.Get<int>("spawnX");
|
||||
playerData.spawnY = reader.Get<int>("spawnY");
|
||||
return playerData;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
|
||||
return playerData;
|
||||
}
|
||||
|
||||
public bool SeedInitialData(User user)
|
||||
{
|
||||
string initialItems = "-15,1,0~-13,1,0~-16,1,45~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0";
|
||||
try
|
||||
{
|
||||
database.Query("INSERT INTO tsCharacter (Account, Health, MaxHealth, Mana, MaxMana, Inventory, spawnX, spawnY) VALUES (@0, @1, @2, @3, @4, @5, @6, @7);", user.ID,
|
||||
100, 100, 20, 20, initialItems, -1, -1);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool InsertPlayerData(TSPlayer player)
|
||||
{
|
||||
PlayerData playerData = player.PlayerData;
|
||||
|
||||
if (!player.IsLoggedIn)
|
||||
return false;
|
||||
|
||||
|
||||
if (!GetPlayerData(player, player.UserID).exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
database.Query("INSERT INTO tsCharacter (Account, Health, MaxHealth, Mana, MaxMana, Inventory, spawnX, spawnY) VALUES (@0, @1, @2, @3, @4, @5, @6, @7);", player.UserID,
|
||||
playerData.health, playerData.maxHealth, playerData.mana, playerData.maxMana, NetItem.ToString(playerData.inventory), player.TPlayer.SpawnX, player.TPlayer.SpawnY);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
database.Query("UPDATE tsCharacter SET Health = @0, MaxHealth = @1, Mana = @2, MaxMana = @3, Inventory = @4, spawnX = @6, spawnY = @7 WHERE Account = @5;", playerData.health, playerData.maxHealth,
|
||||
playerData.mana, playerData.maxMana, NetItem.ToString(playerData.inventory), player.UserID, player.TPlayer.SpawnX, player.TPlayer.SpawnY);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool RemovePlayer(int userid)
|
||||
{
|
||||
try
|
||||
{
|
||||
database.Query("DELETE FROM tsCharacter WHERE Account = @0;", userid);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,18 +53,18 @@ namespace TShockAPI.DB
|
|||
LoadPermisions();
|
||||
|
||||
// Add default groups if they don't exist
|
||||
AddDefaultGroup(TShock.Config.DefaultGuestGroupName, "",
|
||||
AddDefaultGroup("guest", "",
|
||||
string.Join(",", Permissions.canbuild, Permissions.canregister, Permissions.canlogin, Permissions.canpartychat,
|
||||
Permissions.cantalkinthird));
|
||||
Permissions.cantalkinthird, Permissions.canchat));
|
||||
|
||||
AddDefaultGroup("default", TShock.Config.DefaultGuestGroupName,
|
||||
AddDefaultGroup("default", "guest",
|
||||
string.Join(",", Permissions.warp, Permissions.canchangepassword));
|
||||
|
||||
AddDefaultGroup("newadmin", "default",
|
||||
string.Join(",", Permissions.kick, Permissions.editspawn, Permissions.reservedslot));
|
||||
|
||||
AddDefaultGroup("admin", "newadmin",
|
||||
string.Join(",", Permissions.ban, Permissions.whitelist, Permissions.causeevents, Permissions.spawnboss,
|
||||
string.Join(",", Permissions.ban, Permissions.whitelist, "tshock.world.time.*", Permissions.spawnboss,
|
||||
Permissions.spawnmob, Permissions.managewarp, Permissions.time, Permissions.tp, Permissions.slap,
|
||||
Permissions.kill, Permissions.logs,
|
||||
Permissions.immunetokick, Permissions.tphere));
|
||||
|
|
@ -181,7 +181,7 @@ namespace TShockAPI.DB
|
|||
/// <param name="parentname">parent of group</param>
|
||||
/// <param name="permissions">permissions</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, string suffix, string prefix)
|
||||
{
|
||||
Group group = GetGroupByName(name);
|
||||
if (group == null)
|
||||
|
|
@ -210,13 +210,17 @@ namespace TShockAPI.DB
|
|||
|
||||
// Ensure any group validation is also persisted to the DB.
|
||||
var newGroup = new Group(name, parent, chatcolor, permissions);
|
||||
string query = "UPDATE GroupList SET Parent=@0, Commands=@1, ChatColor=@2 WHERE GroupName=@3";
|
||||
if (database.Query(query, parentname, newGroup.Permissions, string.Format("{0},{1},{2}", newGroup.R, newGroup.G, newGroup.B), name) != 1)
|
||||
newGroup.Prefix = prefix;
|
||||
newGroup.Suffix = suffix;
|
||||
string query = "UPDATE GroupList SET Parent=@0, Commands=@1, ChatColor=@2, Suffix=@3, Prefix=@4 WHERE GroupName=@5";
|
||||
if (database.Query(query, parentname, newGroup.Permissions, newGroup.ChatColor, suffix, prefix, name) != 1)
|
||||
throw new GroupManagerException(string.Format("Failed to update group \"{0}\".", name));
|
||||
|
||||
group.ChatColor = chatcolor;
|
||||
group.Permissions = permissions;
|
||||
group.Parent = parent;
|
||||
group.Prefix = prefix;
|
||||
group.Suffix = suffix;
|
||||
}
|
||||
|
||||
#if COMPAT_SIGS
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ namespace TShockAPI.DB
|
|||
table.Columns.Select(
|
||||
c =>
|
||||
"'{0}' {1} {2} {3} {4} {5}".SFormat(c.Name, DbTypeToString(c.Type, c.Length), c.Primary ? "PRIMARY KEY" : "",
|
||||
c.AutoIncrement ? "AUTOINCREMENT" : "", c.NotNull ? "NOT NULL" : "",
|
||||
c.Unique ? "UNIQUE" : ""));
|
||||
c.AutoIncrement ? "AUTOINCREMENT" : "", c.NotNull ? "NOT NULL" : "",
|
||||
c.Unique ? "UNIQUE" : ""));
|
||||
return "CREATE TABLE {0} ({1})".SFormat(EscapeTableName(table.Name), string.Join(", ", columns));
|
||||
}
|
||||
|
||||
|
|
@ -57,14 +57,16 @@ namespace TShockAPI.DB
|
|||
|
||||
private static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
|
||||
{
|
||||
{MySqlDbType.VarChar, "TEXT"},
|
||||
{MySqlDbType.String, "TEXT"},
|
||||
{MySqlDbType.Text, "TEXT"},
|
||||
{MySqlDbType.TinyText, "TEXT"},
|
||||
{MySqlDbType.MediumText, "TEXT"},
|
||||
{MySqlDbType.LongText, "TEXT"},
|
||||
{MySqlDbType.Int32, "INTEGER"},
|
||||
{MySqlDbType.Blob, "BLOB"},
|
||||
{ MySqlDbType.VarChar, "TEXT" },
|
||||
{ MySqlDbType.String, "TEXT" },
|
||||
{ MySqlDbType.Text, "TEXT" },
|
||||
{ MySqlDbType.TinyText, "TEXT" },
|
||||
{ MySqlDbType.MediumText, "TEXT" },
|
||||
{ MySqlDbType.LongText, "TEXT" },
|
||||
{ MySqlDbType.Float, "REAL" },
|
||||
{ MySqlDbType.Double, "REAL" },
|
||||
{ MySqlDbType.Int32, "INTEGER" },
|
||||
{ MySqlDbType.Blob, "BLOB" },
|
||||
};
|
||||
|
||||
public string DbTypeToString(MySqlDbType type, int? length)
|
||||
|
|
@ -72,7 +74,7 @@ namespace TShockAPI.DB
|
|||
string ret;
|
||||
if (TypesAsStrings.TryGetValue(type, out ret))
|
||||
return ret;
|
||||
throw new NotImplementedException(Enum.GetName(typeof (MySqlDbType), type));
|
||||
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
|
||||
}
|
||||
|
||||
protected override string EscapeTableName(string table)
|
||||
|
|
@ -89,12 +91,12 @@ namespace TShockAPI.DB
|
|||
table.Columns.Select(
|
||||
c =>
|
||||
"{0} {1} {2} {3} {4}".SFormat(c.Name, DbTypeToString(c.Type, c.Length), c.Primary ? "PRIMARY KEY" : "",
|
||||
c.AutoIncrement ? "AUTO_INCREMENT" : "", c.NotNull ? "NOT NULL" : ""));
|
||||
c.AutoIncrement ? "AUTO_INCREMENT" : "", c.NotNull ? "NOT NULL" : ""));
|
||||
var uniques = table.Columns.Where(c => c.Unique).Select(c => c.Name);
|
||||
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name), string.Join(", ", columns),
|
||||
uniques.Count() > 0
|
||||
? ", UNIQUE({0})".SFormat(string.Join(", ", uniques))
|
||||
: "");
|
||||
uniques.Count() > 0
|
||||
? ", UNIQUE({0})".SFormat(string.Join(", ", uniques))
|
||||
: "");
|
||||
}
|
||||
|
||||
public override string RenameTable(string from, string to)
|
||||
|
|
@ -104,21 +106,23 @@ namespace TShockAPI.DB
|
|||
|
||||
private static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
|
||||
{
|
||||
{MySqlDbType.VarChar, "VARCHAR"},
|
||||
{MySqlDbType.String, "CHAR"},
|
||||
{MySqlDbType.Text, "TEXT"},
|
||||
{MySqlDbType.TinyText, "TINYTEXT"},
|
||||
{MySqlDbType.MediumText, "MEDIUMTEXT"},
|
||||
{MySqlDbType.LongText, "LONGTEXT"},
|
||||
{MySqlDbType.Int32, "INT"},
|
||||
{ MySqlDbType.VarChar, "VARCHAR" },
|
||||
{ MySqlDbType.String, "CHAR" },
|
||||
{ MySqlDbType.Text, "TEXT" },
|
||||
{ MySqlDbType.TinyText, "TINYTEXT" },
|
||||
{ MySqlDbType.MediumText, "MEDIUMTEXT" },
|
||||
{ MySqlDbType.LongText, "LONGTEXT" },
|
||||
{ MySqlDbType.Float, "FLOAT" },
|
||||
{ MySqlDbType.Double, "DOUBLE" },
|
||||
{ MySqlDbType.Int32, "INT" },
|
||||
};
|
||||
|
||||
public string DbTypeToString(MySqlDbType type, int? length)
|
||||
{
|
||||
string ret;
|
||||
if (TypesAsStrings.TryGetValue(type, out ret))
|
||||
return ret + (length != null ? "({0})".SFormat((int) length) : "");
|
||||
throw new NotImplementedException(Enum.GetName(typeof (MySqlDbType), type));
|
||||
return ret + (length != null ? "({0})".SFormat((int)length) : "");
|
||||
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
|
||||
}
|
||||
|
||||
protected override string EscapeTableName(string table)
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
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.Data;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
public class InventoryManager
|
||||
{
|
||||
public IDbConnection database;
|
||||
|
||||
public InventoryManager(IDbConnection db)
|
||||
{
|
||||
database = db;
|
||||
|
||||
var table = new SqlTable("Inventory",
|
||||
new SqlColumn("Account", MySqlDbType.Int32) {Primary = true},
|
||||
new SqlColumn("MaxHealth", MySqlDbType.Int32),
|
||||
new SqlColumn("MaxMana", MySqlDbType.Int32),
|
||||
new SqlColumn("Inventory", MySqlDbType.Text)
|
||||
);
|
||||
var creator = new SqlTableCreator(db,
|
||||
db.GetSqlType() == SqlType.Sqlite
|
||||
? (IQueryBuilder) new SqliteQueryCreator()
|
||||
: new MysqlQueryCreator());
|
||||
creator.EnsureExists(table);
|
||||
}
|
||||
|
||||
public PlayerData GetPlayerData(TSPlayer player, int acctid)
|
||||
{
|
||||
PlayerData playerData = new PlayerData(player);
|
||||
|
||||
try
|
||||
{
|
||||
using (var reader = database.QueryReader("SELECT * FROM Inventory WHERE Account=@0", acctid))
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
playerData.exists = true;
|
||||
playerData.maxHealth = reader.Get<int>("MaxHealth");
|
||||
playerData.inventory = NetItem.Parse(reader.Get<string>("Inventory"));
|
||||
return playerData;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
|
||||
return playerData;
|
||||
}
|
||||
|
||||
public bool InsertPlayerData(TSPlayer player)
|
||||
{
|
||||
PlayerData playerData = player.PlayerData;
|
||||
|
||||
if (!player.IsLoggedIn)
|
||||
return false;
|
||||
|
||||
if (!GetPlayerData(player, player.UserID).exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
database.Query("INSERT INTO Inventory (Account, MaxHealth, Inventory) VALUES (@0, @1, @2);", player.UserID,
|
||||
playerData.maxHealth, NetItem.ToString(playerData.inventory));
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
database.Query("UPDATE Inventory SET MaxHealth = @0, Inventory = @1 WHERE Account = @2;", playerData.maxHealth,
|
||||
NetItem.ToString(playerData.inventory), player.UserID);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -196,13 +196,32 @@ namespace TShockAPI.DB
|
|||
return Name == other.Name;
|
||||
}
|
||||
|
||||
public bool HasPermissionToUseItem(TSPlayer ply)
|
||||
{
|
||||
if (ply == null)
|
||||
return false;
|
||||
return AllowedGroups.Contains(ply.Group.Name);
|
||||
// could add in the other permissions in this class instead of a giant if switch.
|
||||
}
|
||||
public bool HasPermissionToUseItem(TSPlayer ply)
|
||||
{
|
||||
if (ply == null)
|
||||
return false;
|
||||
|
||||
if (ply.Group.HasPermission(Permissions.usebanneditem))
|
||||
return true;
|
||||
|
||||
var cur = ply.Group;
|
||||
var traversed = new List<Group>();
|
||||
while (cur != null)
|
||||
{
|
||||
if (AllowedGroups.Contains(cur.Name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (traversed.Contains(cur))
|
||||
{
|
||||
throw new InvalidOperationException("Infinite group parenting ({0})".SFormat(cur.Name));
|
||||
}
|
||||
traversed.Add(cur);
|
||||
cur = cur.Parent;
|
||||
}
|
||||
return false;
|
||||
// could add in the other permissions in this class instead of a giant if switch.
|
||||
}
|
||||
|
||||
public void SetAllowedGroups(String groups)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,11 +27,14 @@ namespace TShockAPI.DB
|
|||
{
|
||||
public class RegionManager
|
||||
{
|
||||
/// <summary>
|
||||
/// The list of regions.
|
||||
/// </summary>
|
||||
public List<Region> Regions = new List<Region>();
|
||||
|
||||
private IDbConnection database;
|
||||
|
||||
public RegionManager(IDbConnection db)
|
||||
internal RegionManager(IDbConnection db)
|
||||
{
|
||||
database = db;
|
||||
var table = new SqlTable("Regions",
|
||||
|
|
@ -52,11 +55,12 @@ namespace TShockAPI.DB
|
|||
? (IQueryBuilder) new SqliteQueryCreator()
|
||||
: new MysqlQueryCreator());
|
||||
creator.EnsureExists(table);
|
||||
|
||||
ReloadAllRegions();
|
||||
}
|
||||
|
||||
public void ReloadAllRegions()
|
||||
/// <summary>
|
||||
/// Reloads all regions.
|
||||
/// </summary>
|
||||
public void Reload()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -419,6 +423,33 @@ namespace TShockAPI.DB
|
|||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position of a region.
|
||||
/// </summary>
|
||||
/// <param name="regionName">The region name.</param>
|
||||
/// <param name="x">The X position.</param>
|
||||
/// <param name="y">The Y position.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <returns>Whether the operation succeeded.</returns>
|
||||
public bool PositionRegion(string regionName, int x, int y, int width, int height)
|
||||
{
|
||||
try
|
||||
{
|
||||
Region region = Regions.First(r => String.Equals(regionName, r.Name, StringComparison.OrdinalIgnoreCase));
|
||||
region.Area = new Rectangle(x, y, width, height);
|
||||
|
||||
if (database.Query("UPDATE Regions SET X1 = @0, Y1 = @1, width = @2, height = @3 WHERE RegionName = @4 AND WorldID = @5",
|
||||
x, y, width, height, regionName, Main.worldID.ToString()) > 0)
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the regions names from world
|
||||
/// </summary>
|
||||
|
|
@ -628,8 +659,7 @@ namespace TShockAPI.DB
|
|||
return true;
|
||||
}
|
||||
|
||||
return AllowedIDs.Contains(ply.UserID) || AllowedGroups.Contains(ply.Group.Name) || Owner == ply.UserAccountName ||
|
||||
ply.Group.HasPermission("manageregion");
|
||||
return AllowedIDs.Contains(ply.UserID) || AllowedGroups.Contains(ply.Group.Name) || Owner == ply.UserAccountName;
|
||||
}
|
||||
|
||||
public void setAllowedIDs(String ids)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Data;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -37,7 +38,9 @@ namespace TShockAPI.DB
|
|||
new SqlColumn("ID", MySqlDbType.Int32) {Primary = true, AutoIncrement = true},
|
||||
new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true},
|
||||
new SqlColumn("Password", MySqlDbType.VarChar, 128),
|
||||
new SqlColumn("UUID", MySqlDbType.VarChar, 128),
|
||||
new SqlColumn("Usergroup", MySqlDbType.Text),
|
||||
new SqlColumn("Registered", MySqlDbType.Text),
|
||||
new SqlColumn("LastAccessed", MySqlDbType.Text),
|
||||
new SqlColumn("KnownIPs", MySqlDbType.Text)
|
||||
);
|
||||
|
|
@ -60,8 +63,8 @@ namespace TShockAPI.DB
|
|||
int ret;
|
||||
try
|
||||
{
|
||||
ret = database.Query("INSERT INTO Users (Username, Password, UserGroup) VALUES (@0, @1, @2);", user.Name,
|
||||
TShock.Utils.HashPassword(user.Password), user.Group);
|
||||
ret = database.Query("INSERT INTO Users (Username, Password, UUID, UserGroup, Registered) VALUES (@0, @1, @2, @3, @4);", user.Name,
|
||||
TShock.Utils.HashPassword(user.Password), user.UUID, user.Group, DateTime.UtcNow.ToString("s"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -114,6 +117,26 @@ namespace TShockAPI.DB
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UUID for a given username
|
||||
/// </summary>
|
||||
/// <param name="user">User user</param>
|
||||
/// <param name="group">string uuid</param>
|
||||
public void SetUserUUID(User user, string uuid)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (
|
||||
database.Query("UPDATE Users SET UUID = @0 WHERE Username = @1;", uuid,
|
||||
user.Name) == 0)
|
||||
throw new UserNotExistException(user.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new UserManagerException("SetUserUUID SQL returned an error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the group for a given username
|
||||
/// </summary>
|
||||
|
|
@ -146,7 +169,7 @@ namespace TShockAPI.DB
|
|||
{
|
||||
try
|
||||
{
|
||||
if (database.Query("UPDATE Users SET LastAccessed = @0, KnownIps = @1 WHERE Username = @2;", DateTime.Now.ToString("G"), user.KnownIps, user.Name) == 0)
|
||||
if (database.Query("UPDATE Users SET LastAccessed = @0, KnownIps = @1 WHERE Username = @2;", DateTime.UtcNow.ToString("s"), user.KnownIps, user.Name) == 0)
|
||||
throw new UserNotExistException(user.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -267,7 +290,9 @@ namespace TShockAPI.DB
|
|||
user.ID = result.Get<int>("ID");
|
||||
user.Group = result.Get<string>("Usergroup");
|
||||
user.Password = result.Get<string>("Password");
|
||||
user.UUID = result.Get<string>("UUID");
|
||||
user.Name = result.Get<string>("Username");
|
||||
user.Registered = result.Get<string>("Registered");
|
||||
user.LastAccessed = result.Get<string>("LastAccessed");
|
||||
user.KnownIps = result.Get<string>("KnownIps");
|
||||
return user;
|
||||
|
|
@ -279,15 +304,19 @@ namespace TShockAPI.DB
|
|||
public int ID { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string UUID { get; set; }
|
||||
public string Group { get; set; }
|
||||
public string Registered { get; set; }
|
||||
public string LastAccessed { get; set; }
|
||||
public string KnownIps { get; set; }
|
||||
|
||||
public User(string name, string pass, string group, string last, string known)
|
||||
public User(string name, string pass, string uuid, string group, string registered, string last, string known)
|
||||
{
|
||||
Name = name;
|
||||
Password = pass;
|
||||
UUID = uuid;
|
||||
Group = group;
|
||||
Registered = registered;
|
||||
LastAccessed = last;
|
||||
KnownIps = known;
|
||||
}
|
||||
|
|
@ -296,7 +325,9 @@ namespace TShockAPI.DB
|
|||
{
|
||||
Name = "";
|
||||
Password = "";
|
||||
UUID = "";
|
||||
Group = "";
|
||||
Registered = "";
|
||||
LastAccessed = "";
|
||||
KnownIps = "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Terraria;
|
||||
|
||||
|
|
@ -28,9 +29,13 @@ namespace TShockAPI.DB
|
|||
public class WarpManager
|
||||
{
|
||||
private IDbConnection database;
|
||||
/// <summary>
|
||||
/// The list of warps.
|
||||
/// </summary>
|
||||
public List<Warp> Warps = new List<Warp>();
|
||||
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
|
||||
public WarpManager(IDbConnection db)
|
||||
internal WarpManager(IDbConnection db)
|
||||
{
|
||||
database = db;
|
||||
|
||||
|
|
@ -48,12 +53,23 @@ namespace TShockAPI.DB
|
|||
creator.EnsureExists(table);
|
||||
}
|
||||
|
||||
public bool AddWarp(int x, int y, string name, string worldid)
|
||||
/// <summary>
|
||||
/// Adds a warp.
|
||||
/// </summary>
|
||||
/// <param name="x">The X position.</param>
|
||||
/// <param name="y">The Y position.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>Whether the opration succeeded.</returns>
|
||||
public bool Add(int x, int y, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
database.Query("INSERT INTO Warps (X, Y, WarpName, WorldID) VALUES (@0, @1, @2, @3);", x, y, name, worldid);
|
||||
return true;
|
||||
if (database.Query("INSERT INTO Warps (X, Y, WarpName, WorldID) VALUES (@0, @1, @2, @3);",
|
||||
x, y, name, Main.worldID.ToString()) > 0)
|
||||
{
|
||||
Warps.Add(new Warp(new Point(x, y), name));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -62,12 +78,41 @@ namespace TShockAPI.DB
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool RemoveWarp(string name)
|
||||
/// <summary>
|
||||
/// Reloads all warps.
|
||||
/// </summary>
|
||||
public void ReloadWarps()
|
||||
{
|
||||
Warps.Clear();
|
||||
|
||||
using (var reader = database.QueryReader("SELECT * FROM Warps WHERE WorldID = @0",
|
||||
Main.worldID.ToString()))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
Warps.Add(new Warp(
|
||||
new Point(reader.Get<int>("X"), reader.Get<int>("Y")),
|
||||
reader.Get<string>("WarpName"),
|
||||
(reader.Get<string>("Private") ?? "0") != "0"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a warp.
|
||||
/// </summary>
|
||||
/// <param name="warpName">The warp name.</param>
|
||||
/// <returns>Whether the operation succeeded.</returns>
|
||||
public bool Remove(string warpName)
|
||||
{
|
||||
try
|
||||
{
|
||||
database.Query("DELETE FROM Warps WHERE WarpName=@0 AND WorldID=@1", name, Main.worldID.ToString());
|
||||
return true;
|
||||
if (database.Query("DELETE FROM Warps WHERE WarpName = @0 AND WorldID = @1",
|
||||
warpName, Main.worldID.ToString()) > 0)
|
||||
{
|
||||
Warps.RemoveAll(w => String.Equals(w.Name, warpName, StringComparison.OrdinalIgnoreCase));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -76,113 +121,121 @@ namespace TShockAPI.DB
|
|||
return false;
|
||||
}
|
||||
|
||||
public Warp FindWarp(string name)
|
||||
/// <summary>
|
||||
/// Finds the warp with the given name.
|
||||
/// </summary>
|
||||
/// <param name="warpName">The name.</param>
|
||||
/// <returns>The warp, if it exists, or else null.</returns>
|
||||
public Warp Find(string warpName)
|
||||
{
|
||||
return Warps.FirstOrDefault(w => String.Equals(w.Name, warpName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
/// <summary>
|
||||
/// Finds the warp with the given name.
|
||||
/// </summary>
|
||||
/// <param name="warpName">The name.</param>
|
||||
/// <returns>The warp, if it exists, or else null.</returns>
|
||||
[Obsolete]
|
||||
public Warp FindWarp(string warpName)
|
||||
{
|
||||
return Warps.FirstOrDefault(w => String.Equals(w.Name, warpName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position of a warp.
|
||||
/// </summary>
|
||||
/// <param name="warpName">The warp name.</param>
|
||||
/// <param name="x">The X position.</param>
|
||||
/// <param name="y">The Y position.</param>
|
||||
/// <returns>Whether the operation suceeded.</returns>
|
||||
public bool Position(string warpName, int x, int y)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (
|
||||
var reader = database.QueryReader("SELECT * FROM Warps WHERE WarpName=@0 AND WorldID=@1", name,
|
||||
Main.worldID.ToString()))
|
||||
if (database.Query("UPDATE Warps SET X = @0, Y = @1 WHERE WarpName = @2 AND WorldID = @3",
|
||||
x, y, warpName, Main.worldID.ToString()) > 0)
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Warp(new Vector2(reader.Get<int>("X"), reader.Get<int>("Y")), reader.Get<string>("WarpName"),
|
||||
reader.Get<string>("WorldID"), reader.Get<string>("Private"));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Warp(new Vector2(reader.Get<int>("X"), reader.Get<int>("Y")), reader.Get<string>("WarpName"),
|
||||
reader.Get<string>("WorldID"), "0");
|
||||
}
|
||||
}
|
||||
Warps.Find(w => String.Equals(w.Name, warpName, StringComparison.OrdinalIgnoreCase)).Position = new Point(x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
return new Warp();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the warps names from world
|
||||
/// Sets the hidden state of a warp.
|
||||
/// </summary>
|
||||
/// <param name="worldid">World name to get warps from</param>
|
||||
/// <returns>List of warps with only their names</returns>
|
||||
public List<Warp> ListAllPublicWarps(string worldid)
|
||||
/// <param name="warpName">The warp name.</param>
|
||||
/// <param name="state">The state.</param>
|
||||
/// <returns>Whether the operation suceeded.</returns>
|
||||
public bool Hide(string warpName, bool state)
|
||||
{
|
||||
var warps = new List<Warp>();
|
||||
try
|
||||
{
|
||||
using (var reader = database.QueryReader("SELECT * FROM Warps WHERE WorldID=@0", worldid))
|
||||
if (database.Query("UPDATE Warps SET Private = @0 WHERE WarpName = @1 AND WorldID = @2",
|
||||
state ? "1" : "0", warpName, Main.worldID.ToString()) > 0)
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (reader.Get<String>("Private") == "0" || reader.Get<String>("Private") == null)
|
||||
warps.Add(new Warp {WarpName = reader.Get<string>("WarpName")});
|
||||
}
|
||||
catch
|
||||
{
|
||||
warps.Add(new Warp {WarpName = reader.Get<string>("WarpName")});
|
||||
}
|
||||
}
|
||||
Warps.Find(w => String.Equals(w.Name, warpName, StringComparison.OrdinalIgnoreCase)).IsPrivate = state;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
return warps;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the warps names from world
|
||||
/// </summary>
|
||||
/// <param name="worldid">World name to get warps from</param>
|
||||
/// <returns>List of warps with only their names</returns>
|
||||
public bool HideWarp(string warp, bool state)
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = "UPDATE Warps SET Private=@0 WHERE WarpName=@1 AND WorldID=@2";
|
||||
|
||||
database.Query(query, state ? "1" : "0", warp, Main.worldID.ToString());
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a warp.
|
||||
/// </summary>
|
||||
public class Warp
|
||||
{
|
||||
public Vector2 WarpPos { get; set; }
|
||||
public string WarpName { get; set; }
|
||||
public string WorldWarpID { get; set; }
|
||||
public string Private { get; set; }
|
||||
|
||||
public Warp(Vector2 warppos, string name, string worldid, string hidden)
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the warp's privacy state.
|
||||
/// </summary>
|
||||
public bool IsPrivate { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the position.
|
||||
/// </summary>
|
||||
public Point Position { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the position.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public Vector2 WarpPos
|
||||
{
|
||||
WarpPos = warppos;
|
||||
WarpName = name;
|
||||
WorldWarpID = worldid;
|
||||
Private = hidden;
|
||||
get { return new Vector2(Position.X, Position.Y); }
|
||||
set { Position = new Point((int)value.X, (int)value.Y); }
|
||||
}
|
||||
|
||||
public Warp(Point position, string name, bool isPrivate = false)
|
||||
{
|
||||
Name = name;
|
||||
Position = position;
|
||||
IsPrivate = isPrivate;
|
||||
}
|
||||
[Obsolete]
|
||||
public Warp(Vector2 position, string name, bool isPrivate = false)
|
||||
{
|
||||
Name = name;
|
||||
WarpPos = position;
|
||||
IsPrivate = isPrivate;
|
||||
}
|
||||
public Warp()
|
||||
{
|
||||
WarpPos = Vector2.Zero;
|
||||
WarpName = null;
|
||||
WorldWarpID = string.Empty;
|
||||
Private = "0";
|
||||
Position = Point.Zero;
|
||||
Name = "";
|
||||
IsPrivate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
1841
TShockAPI/GetDataHandlers.cs
Normal file → Executable file
1841
TShockAPI/GetDataHandlers.cs
Normal file → Executable file
File diff suppressed because it is too large
Load diff
|
|
@ -70,11 +70,11 @@ namespace TShockAPI
|
|||
|
||||
/// <summary>
|
||||
/// The chat color of the group.
|
||||
/// Returns "255255255", sets "255,255,255"
|
||||
/// Returns "255,255,255", sets "255,255,255"
|
||||
/// </summary>
|
||||
public string ChatColor
|
||||
{
|
||||
get { return string.Format("{0}{1}{2}", R.ToString("X2"), G.ToString("X2"), B.ToString("X2")); }
|
||||
get { return string.Format("{0},{1},{2}", R.ToString("D3"), G.ToString("D3"), B.ToString("D3")); }
|
||||
set
|
||||
{
|
||||
if (null != value)
|
||||
|
|
@ -118,7 +118,7 @@ namespace TShockAPI
|
|||
/// <summary>
|
||||
/// The permissions of this group and all that it inherits from.
|
||||
/// </summary>
|
||||
public List<string> TotalPermissions
|
||||
public virtual List<string> TotalPermissions
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
@ -175,24 +175,30 @@ namespace TShockAPI
|
|||
/// <param name="permission">The permission to check.</param>
|
||||
/// <returns>Returns true if the user has that permission.</returns>
|
||||
public virtual bool HasPermission(string permission)
|
||||
{
|
||||
if (String.IsNullOrEmpty(permission) || RealHasPermission(permission))
|
||||
{
|
||||
bool negated = false;
|
||||
if (String.IsNullOrEmpty(permission) || (RealHasPermission(permission, ref negated) && !negated))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (negated)
|
||||
return false;
|
||||
|
||||
string[] nodes = permission.Split('.');
|
||||
for (int i = nodes.Length - 1; i >= 0; i--)
|
||||
{
|
||||
nodes[i] = "*";
|
||||
if (RealHasPermission(String.Join(".", nodes, 0, i + 1)))
|
||||
if (RealHasPermission(String.Join(".", nodes, 0, i + 1), ref negated))
|
||||
{
|
||||
return true;
|
||||
return !negated;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private bool RealHasPermission(string permission)
|
||||
private bool RealHasPermission(string permission, ref bool negated)
|
||||
{
|
||||
negated = false;
|
||||
if (string.IsNullOrEmpty(permission))
|
||||
return true;
|
||||
|
||||
|
|
@ -200,9 +206,12 @@ namespace TShockAPI
|
|||
var traversed = new List<Group>();
|
||||
while (cur != null)
|
||||
{
|
||||
if (cur.negatedpermissions.Contains(permission))
|
||||
return false;
|
||||
if (cur.permissions.Contains(permission))
|
||||
if (cur.negatedpermissions.Contains(permission))
|
||||
{
|
||||
negated = true;
|
||||
return false;
|
||||
}
|
||||
if (cur.permissions.Contains(permission))
|
||||
return true;
|
||||
if (traversed.Contains(cur))
|
||||
{
|
||||
|
|
@ -226,6 +235,12 @@ namespace TShockAPI
|
|||
negatedpermissions.Add(permission);
|
||||
permissions.Remove(permission); // Ensure we don't have conflicting definitions for a permissions
|
||||
}
|
||||
|
||||
for (int i = 0; i < TShock.Players.Length; i++)
|
||||
{
|
||||
if (TShock.Players[i] != null && TShock.Players[i].IsRaptor)
|
||||
TShock.Players[i].SendRaptorPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -245,6 +260,12 @@ namespace TShockAPI
|
|||
permissions.Add(permission);
|
||||
negatedpermissions.Remove(permission); // Ensure we don't have conflicting definitions for a permissions
|
||||
}
|
||||
|
||||
for (int i = 0; i < TShock.Players.Length; i++)
|
||||
{
|
||||
if (TShock.Players[i] != null && TShock.Players[i].IsRaptor)
|
||||
TShock.Players[i].SendRaptorPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -272,6 +293,11 @@ namespace TShockAPI
|
|||
return;
|
||||
}
|
||||
permissions.Remove(permission);
|
||||
for (int i = 0; i < TShock.Players.Length; i++)
|
||||
{
|
||||
if (TShock.Players[i] != null && TShock.Players[i].IsRaptor && TShock.Players[i].Group == this)
|
||||
TShock.Players[i].SendRaptorPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -300,6 +326,10 @@ namespace TShockAPI
|
|||
/// </summary>
|
||||
public class SuperAdminGroup : Group
|
||||
{
|
||||
public override List<string> TotalPermissions
|
||||
{
|
||||
get { return new List<string> { "*" }; }
|
||||
}
|
||||
public SuperAdminGroup()
|
||||
: base("superadmin")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ namespace TShockAPI.Hooks
|
|||
|
||||
public static void OnPlayerPostLogin(TSPlayer ply)
|
||||
{
|
||||
if(PlayerPostLogin == null)
|
||||
if (PlayerPostLogin == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ namespace TShockAPI
|
|||
/// </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)
|
||||
public static void Data(string format, params object[] args)
|
||||
{
|
||||
Data(String.Format(format, args));
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ namespace TShockAPI
|
|||
/// </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)
|
||||
public static void Error(string format, params object[] args)
|
||||
{
|
||||
Error(String.Format(format, args));
|
||||
}
|
||||
|
|
@ -119,7 +119,7 @@ namespace TShockAPI
|
|||
/// </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)
|
||||
public static void ConsoleError(string format, params object[] args)
|
||||
{
|
||||
ConsoleError(String.Format(format, args));
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ namespace TShockAPI
|
|||
/// </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)
|
||||
public static void Warn(string format, params object[] args)
|
||||
{
|
||||
Warn(String.Format(format, args));
|
||||
}
|
||||
|
|
@ -157,7 +157,7 @@ namespace TShockAPI
|
|||
/// </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)
|
||||
public static void Info(string format, params object[] args)
|
||||
{
|
||||
Info(String.Format(format, args));
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ namespace TShockAPI
|
|||
/// </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)
|
||||
public static void ConsoleInfo(string format, params object[] args)
|
||||
{
|
||||
ConsoleInfo(String.Format(format, args));
|
||||
}
|
||||
|
|
@ -198,7 +198,7 @@ namespace TShockAPI
|
|||
/// </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)
|
||||
public static void Debug(string format, params object[] args)
|
||||
{
|
||||
Debug(String.Format(format, args));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,32 @@ namespace TShockAPI.Net
|
|||
public byte Type { get; set; }
|
||||
public short FrameX { get; set; }
|
||||
public short FrameY { get; set; }
|
||||
public bool Lighted { get; set; }
|
||||
public byte Wall { get; set; }
|
||||
public byte Liquid { get; set; }
|
||||
public bool Lava { get; set; }
|
||||
public byte LiquidType { get; set; }
|
||||
public bool Wire { get; set; }
|
||||
public bool Wire2 { get; set; }
|
||||
public bool Wire3 { get; set; }
|
||||
public byte HalfBrick { get; set; }
|
||||
public byte Actuator { get; set; }
|
||||
public bool Inactive { get; set; }
|
||||
public bool IsHalf { get; set; }
|
||||
public bool IsActuator { get; set; }
|
||||
public byte TileColor { get; set; }
|
||||
public byte WallColor { get; set; }
|
||||
public bool Slope { get; set; }
|
||||
public bool Slope2 { get; set; }
|
||||
|
||||
public bool HasColor
|
||||
{
|
||||
get { return TileColor > 0; }
|
||||
}
|
||||
|
||||
public bool HasWallColor
|
||||
{
|
||||
get { return WallColor > 0; }
|
||||
}
|
||||
|
||||
public bool HasWall
|
||||
{
|
||||
|
|
@ -57,8 +79,17 @@ namespace TShockAPI.Net
|
|||
FrameY = -1;
|
||||
Wall = 0;
|
||||
Liquid = 0;
|
||||
Lava = false;
|
||||
Wire = false;
|
||||
Wire2 = false;
|
||||
Wire3 = false;
|
||||
HalfBrick = 0;
|
||||
Actuator = 0;
|
||||
Inactive = false;
|
||||
TileColor = 0;
|
||||
WallColor = 0;
|
||||
Lighted = false;
|
||||
Slope = false;
|
||||
Slope2 = false;
|
||||
}
|
||||
|
||||
public NetTile(Stream stream)
|
||||
|
|
@ -71,9 +102,12 @@ namespace TShockAPI.Net
|
|||
{
|
||||
var flags = TileFlags.None;
|
||||
|
||||
if (Active)
|
||||
if ((Active) && (!Inactive))
|
||||
flags |= TileFlags.Active;
|
||||
|
||||
if (Lighted)
|
||||
flags |= TileFlags.Lighted;
|
||||
|
||||
if (HasWall)
|
||||
flags |= TileFlags.Wall;
|
||||
|
||||
|
|
@ -82,9 +116,53 @@ namespace TShockAPI.Net
|
|||
|
||||
if (Wire)
|
||||
flags |= TileFlags.Wire;
|
||||
|
||||
if (IsHalf)
|
||||
flags |= TileFlags.HalfBrick;
|
||||
|
||||
if (IsActuator)
|
||||
flags |= TileFlags.Actuator;
|
||||
|
||||
if (Inactive)
|
||||
{
|
||||
flags |= TileFlags.Inactive;
|
||||
}
|
||||
|
||||
stream.WriteInt8((byte) flags);
|
||||
|
||||
var flags2 = TileFlags2.None;
|
||||
|
||||
if ((Wire2))
|
||||
flags2 |= TileFlags2.Wire2;
|
||||
|
||||
if (Wire3)
|
||||
flags2 |= TileFlags2.Wire3;
|
||||
|
||||
if (HasColor)
|
||||
flags2 |= TileFlags2.Color;
|
||||
|
||||
if (HasWallColor)
|
||||
flags2 |= TileFlags2.WallColor;
|
||||
|
||||
if (Slope)
|
||||
flags2 |= TileFlags2.Slope;
|
||||
|
||||
if (Slope2)
|
||||
flags2 |= TileFlags2.Slope2;
|
||||
|
||||
|
||||
stream.WriteInt8((byte)flags2);
|
||||
|
||||
if (HasColor)
|
||||
{
|
||||
stream.WriteByte(TileColor);
|
||||
}
|
||||
|
||||
if (HasWallColor)
|
||||
{
|
||||
stream.WriteByte(WallColor);
|
||||
}
|
||||
|
||||
if (Active)
|
||||
{
|
||||
stream.WriteInt8(Type);
|
||||
|
|
@ -101,13 +179,29 @@ namespace TShockAPI.Net
|
|||
if (HasLiquid)
|
||||
{
|
||||
stream.WriteInt8(Liquid);
|
||||
stream.WriteBoolean(Lava);
|
||||
stream.WriteInt8(LiquidType);
|
||||
}
|
||||
}
|
||||
|
||||
public void Unpack(Stream stream)
|
||||
{
|
||||
var flags = (TileFlags) stream.ReadInt8();
|
||||
var flags2 = (TileFlags2)stream.ReadInt8();
|
||||
|
||||
Wire2 = flags2.HasFlag(TileFlags2.Wire2);
|
||||
Wire3 = flags2.HasFlag(TileFlags2.Wire3);
|
||||
Slope = flags2.HasFlag(TileFlags2.Slope);
|
||||
Slope2 = flags2.HasFlag(TileFlags2.Slope2);
|
||||
|
||||
if (flags2.HasFlag(TileFlags2.Color))
|
||||
{
|
||||
TileColor = stream.ReadInt8();
|
||||
}
|
||||
|
||||
if (flags2.HasFlag(TileFlags2.WallColor))
|
||||
{
|
||||
WallColor = stream.ReadInt8();
|
||||
}
|
||||
|
||||
Active = flags.HasFlag(TileFlags.Active);
|
||||
if (Active)
|
||||
|
|
@ -120,6 +214,11 @@ namespace TShockAPI.Net
|
|||
}
|
||||
}
|
||||
|
||||
if (flags.HasFlag(TileFlags.Lighted))
|
||||
{
|
||||
Lighted = true;
|
||||
}
|
||||
|
||||
if (flags.HasFlag(TileFlags.Wall))
|
||||
{
|
||||
Wall = stream.ReadInt8();
|
||||
|
|
@ -128,11 +227,23 @@ namespace TShockAPI.Net
|
|||
if (flags.HasFlag(TileFlags.Liquid))
|
||||
{
|
||||
Liquid = stream.ReadInt8();
|
||||
Lava = stream.ReadBoolean();
|
||||
LiquidType = stream.ReadInt8();
|
||||
}
|
||||
|
||||
if (flags.HasFlag(TileFlags.Wire))
|
||||
Wire = true;
|
||||
|
||||
if (flags.HasFlag(TileFlags.HalfBrick))
|
||||
IsHalf = true;
|
||||
|
||||
if (flags.HasFlag(TileFlags.Actuator))
|
||||
IsActuator = true;
|
||||
|
||||
if (flags.HasFlag(TileFlags.Inactive))
|
||||
{
|
||||
Inactive = true;
|
||||
Active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,6 +255,21 @@ namespace TShockAPI.Net
|
|||
Lighted = 2,
|
||||
Wall = 4,
|
||||
Liquid = 8,
|
||||
Wire = 16
|
||||
Wire = 16,
|
||||
HalfBrick = 32,
|
||||
Actuator = 64,
|
||||
Inactive = 128
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum TileFlags2 : byte
|
||||
{
|
||||
None = 0,
|
||||
Wire2 = 1,
|
||||
Wire3 = 2,
|
||||
Color = 4,
|
||||
WallColor = 8,
|
||||
Slope = 16,
|
||||
Slope2 = 32
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace TShockAPI.Net
|
|||
{
|
||||
public override PacketTypes ID
|
||||
{
|
||||
get { return PacketTypes.ProjectileNew; }
|
||||
get{ return PacketTypes.ProjectileNew; }
|
||||
}
|
||||
|
||||
public short Index { get; set; }
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ using System.Text;
|
|||
namespace TShockAPI.Net
|
||||
{
|
||||
[Flags]
|
||||
public enum WorldInfoFlag : byte
|
||||
public enum BossFlags : byte
|
||||
{
|
||||
None = 0,
|
||||
OrbSmashed = 1,
|
||||
|
|
@ -32,7 +32,21 @@ namespace TShockAPI.Net
|
|||
DownedBoss2 = 4,
|
||||
DownedBoss3 = 8,
|
||||
HardMode = 16,
|
||||
DownedClown = 32
|
||||
DownedClown = 32,
|
||||
ServerSideCharacter = 64
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum BossFlags2 : byte
|
||||
{
|
||||
None = 0,
|
||||
DownedMechBoss1 = 1,
|
||||
DownedMechBoss2 = 2,
|
||||
DownedMechBoss3 = 4,
|
||||
DownedMechBossAny = 8,
|
||||
CloudBg = 16,
|
||||
Crimson = 32,
|
||||
Pumpkin = 64
|
||||
}
|
||||
|
||||
public class WorldInfoMsg : BaseMsg
|
||||
|
|
@ -41,6 +55,7 @@ namespace TShockAPI.Net
|
|||
public bool DayTime { get; set; }
|
||||
public byte MoonPhase { get; set; }
|
||||
public bool BloodMoon { get; set; }
|
||||
public bool Eclipse { get; set; }
|
||||
public int MaxTilesX { get; set; }
|
||||
public int MaxTilesY { get; set; }
|
||||
public int SpawnX { get; set; }
|
||||
|
|
@ -48,7 +63,37 @@ namespace TShockAPI.Net
|
|||
public int WorldSurface { get; set; }
|
||||
public int RockLayer { get; set; }
|
||||
public int WorldID { get; set; }
|
||||
public WorldInfoFlag WorldFlags { get; set; }
|
||||
public byte MoonType { get; set; }
|
||||
public int TreeX0 { get; set; }
|
||||
public int TreeX1 { get; set; }
|
||||
public int TreeX2 { get; set; }
|
||||
public byte TreeStyle0 { get; set; }
|
||||
public byte TreeStyle1 { get; set; }
|
||||
public byte TreeStyle2 { get; set; }
|
||||
public byte TreeStyle3 { get; set; }
|
||||
public int CaveBackX0 { get; set; }
|
||||
public int CaveBackX1 { get; set; }
|
||||
public int CaveBackX2 { get; set; }
|
||||
public byte CaveBackStyle0 { get; set; }
|
||||
public byte CaveBackStyle1 { get; set; }
|
||||
public byte CaveBackStyle2 { get; set; }
|
||||
public byte CaveBackStyle3 { get; set; }
|
||||
public byte SetBG0 { get; set; }
|
||||
public byte SetBG1 { get; set; }
|
||||
public byte SetBG2 { get; set; }
|
||||
public byte SetBG3 { get; set; }
|
||||
public byte SetBG4 { get; set; }
|
||||
public byte SetBG5 { get; set; }
|
||||
public byte SetBG6 { get; set; }
|
||||
public byte SetBG7 { get; set; }
|
||||
public byte IceBackStyle { get; set; }
|
||||
public byte JungleBackStyle { get; set; }
|
||||
public byte HellBackStyle { get; set; }
|
||||
public float WindSpeed { get; set; }
|
||||
public byte NumberOfClouds { get; set; }
|
||||
public BossFlags BossFlags { get; set; }
|
||||
public BossFlags2 BossFlags2 { get; set; }
|
||||
public float Rain { get; set; }
|
||||
public string WorldName { get; set; }
|
||||
|
||||
public override PacketTypes ID
|
||||
|
|
@ -62,6 +107,7 @@ namespace TShockAPI.Net
|
|||
stream.WriteBoolean(DayTime);
|
||||
stream.WriteInt8(MoonPhase);
|
||||
stream.WriteBoolean(BloodMoon);
|
||||
stream.WriteBoolean(Eclipse);
|
||||
stream.WriteInt32(MaxTilesX);
|
||||
stream.WriteInt32(MaxTilesY);
|
||||
stream.WriteInt32(SpawnX);
|
||||
|
|
@ -69,7 +115,37 @@ namespace TShockAPI.Net
|
|||
stream.WriteInt32(WorldSurface);
|
||||
stream.WriteInt32(RockLayer);
|
||||
stream.WriteInt32(WorldID);
|
||||
stream.WriteInt8((byte) WorldFlags);
|
||||
stream.WriteByte(MoonType);
|
||||
stream.WriteInt32(TreeX0);
|
||||
stream.WriteInt32(TreeX1);
|
||||
stream.WriteInt32(TreeX2);
|
||||
stream.WriteByte(TreeStyle0);
|
||||
stream.WriteByte(TreeStyle1);
|
||||
stream.WriteByte(TreeStyle2);
|
||||
stream.WriteByte(TreeStyle3);
|
||||
stream.WriteInt32(CaveBackX0);
|
||||
stream.WriteInt32(CaveBackX1);
|
||||
stream.WriteInt32(CaveBackX2);
|
||||
stream.WriteByte(CaveBackStyle0);
|
||||
stream.WriteByte(CaveBackStyle1);
|
||||
stream.WriteByte(CaveBackStyle2);
|
||||
stream.WriteByte(CaveBackStyle3);
|
||||
stream.WriteByte(SetBG0);
|
||||
stream.WriteByte(SetBG1);
|
||||
stream.WriteByte(SetBG2);
|
||||
stream.WriteByte(SetBG3);
|
||||
stream.WriteByte(SetBG4);
|
||||
stream.WriteByte(SetBG5);
|
||||
stream.WriteByte(SetBG6);
|
||||
stream.WriteByte(SetBG7);
|
||||
stream.WriteByte(IceBackStyle);
|
||||
stream.WriteByte(JungleBackStyle);
|
||||
stream.WriteByte(HellBackStyle);
|
||||
stream.WriteSingle(WindSpeed);
|
||||
stream.WriteByte(NumberOfClouds);
|
||||
stream.WriteInt8((byte)BossFlags);
|
||||
stream.WriteInt8((byte)BossFlags2);
|
||||
stream.WriteSingle(Rain);
|
||||
stream.WriteBytes(Encoding.UTF8.GetBytes(WorldName));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ using System.ComponentModel;
|
|||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using Hooks;
|
||||
using Terraria;
|
||||
using TerrariaApi.Server;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
|
|
@ -34,6 +34,8 @@ namespace TShockAPI
|
|||
/// </summary>
|
||||
public int BytesPerUpdate { get; set; }
|
||||
|
||||
private readonly TShock plugin;
|
||||
|
||||
private PacketBuffer[] buffers = new PacketBuffer[Netplay.serverSock.Length];
|
||||
|
||||
private int[] Bytes = new int[52];
|
||||
|
|
@ -45,8 +47,9 @@ namespace TShockAPI
|
|||
Command flush;
|
||||
#endif
|
||||
|
||||
public PacketBufferer()
|
||||
public PacketBufferer(TShock p)
|
||||
{
|
||||
plugin = p;
|
||||
BytesPerUpdate = 0xFFFF;
|
||||
for (int i = 0; i < buffers.Length; i++)
|
||||
buffers[i] = new PacketBuffer();
|
||||
|
|
@ -58,9 +61,9 @@ namespace TShockAPI
|
|||
Commands.ChatCommands.Add(flush);
|
||||
#endif
|
||||
|
||||
NetHooks.SendBytes += ServerHooks_SendBytes;
|
||||
ServerHooks.SocketReset += ServerHooks_SocketReset;
|
||||
GameHooks.PostUpdate += GameHooks_Update;
|
||||
ServerApi.Hooks.NetSendBytes.Register(plugin, ServerHooks_SendBytes);
|
||||
ServerApi.Hooks.ServerSocketReset.Register(plugin, ServerHooks_SocketReset);
|
||||
ServerApi.Hooks.GamePostUpdate.Register(plugin, GameHooks_Update);
|
||||
}
|
||||
|
||||
~PacketBufferer()
|
||||
|
|
@ -82,9 +85,9 @@ namespace TShockAPI
|
|||
Commands.ChatCommands.Remove(dump);
|
||||
Commands.ChatCommands.Remove(flush);
|
||||
#endif
|
||||
NetHooks.SendBytes -= ServerHooks_SendBytes;
|
||||
ServerHooks.SocketReset -= ServerHooks_SocketReset;
|
||||
GameHooks.PostUpdate -= GameHooks_Update;
|
||||
ServerApi.Hooks.NetSendBytes.Deregister(plugin, ServerHooks_SendBytes);
|
||||
ServerApi.Hooks.ServerSocketReset.Deregister(plugin, ServerHooks_SocketReset);
|
||||
ServerApi.Hooks.GamePostUpdate.Deregister(plugin, GameHooks_Update);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +110,7 @@ namespace TShockAPI
|
|||
Compressed = new int[52];
|
||||
}
|
||||
|
||||
private void GameHooks_Update()
|
||||
private void GameHooks_Update(EventArgs args)
|
||||
{
|
||||
FlushAll();
|
||||
}
|
||||
|
|
@ -148,9 +151,9 @@ namespace TShockAPI
|
|||
}
|
||||
|
||||
|
||||
private void ServerHooks_SocketReset(ServerSock socket)
|
||||
private void ServerHooks_SocketReset(SocketResetEventArgs args)
|
||||
{
|
||||
buffers[socket.whoAmI] = new PacketBuffer();
|
||||
buffers[args.Socket.whoAmI] = new PacketBuffer();
|
||||
}
|
||||
|
||||
public bool SendBytes(ServerSock socket, byte[] buffer)
|
||||
|
|
@ -179,6 +182,12 @@ namespace TShockAPI
|
|||
{
|
||||
buffers[socket.whoAmI].AddRange(ms.ToArray());
|
||||
}
|
||||
|
||||
if (TShock.Config.EnableMaxBytesInBuffer && buffers[socket.whoAmI].Count > TShock.Config.MaxBytesInBuffer)
|
||||
{
|
||||
buffers[socket.whoAmI].Clear();
|
||||
socket.kill = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +213,7 @@ namespace TShockAPI
|
|||
switch ((uint)e.ErrorCode)
|
||||
{
|
||||
case 0x80004005:
|
||||
case 10053:
|
||||
break;
|
||||
default:
|
||||
Log.Warn(e.ToString());
|
||||
|
|
@ -217,10 +227,10 @@ namespace TShockAPI
|
|||
return false;
|
||||
}
|
||||
|
||||
private void ServerHooks_SendBytes(ServerSock socket, byte[] buffer, int offset, int count, HandledEventArgs e)
|
||||
private void ServerHooks_SendBytes(SendBytesEventArgs args)
|
||||
{
|
||||
e.Handled = true;
|
||||
BufferBytes(socket, buffer, offset, count);
|
||||
args.Handled = true;
|
||||
BufferBytes(args.Socket, args.Buffer, args.Offset, args.Count);
|
||||
}
|
||||
|
||||
#if DEBUG_NET
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ using System.Text;
|
|||
|
||||
namespace TShockAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides tools for sending paginated output.
|
||||
/// </summary>
|
||||
public static class PaginationTools
|
||||
{
|
||||
public delegate Tuple<string, Color> LineFormatterDelegate(object lineData, int lineIndex, int pageNumber);
|
||||
|
|
@ -105,7 +108,7 @@ namespace TShockAPI
|
|||
this.FooterTextColor = Color.Yellow;
|
||||
this.NothingToDisplayString = null;
|
||||
this.LineFormatter = null;
|
||||
this.LineTextColor = Color.White;
|
||||
this.LineTextColor = Color.Yellow;
|
||||
this.maxLinesPerPage = 4;
|
||||
this.pageLimit = 0;
|
||||
}
|
||||
|
|
@ -122,14 +125,10 @@ namespace TShockAPI
|
|||
{
|
||||
if (settings.NothingToDisplayString != null)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
if (!player.RealPlayer)
|
||||
player.SendSuccessMessage(settings.NothingToDisplayString);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendMessage(settings.NothingToDisplayString, settings.HeaderTextColor);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -142,14 +141,10 @@ namespace TShockAPI
|
|||
|
||||
if (settings.IncludeHeader)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
if (!player.RealPlayer)
|
||||
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;
|
||||
|
|
@ -196,14 +191,10 @@ namespace TShockAPI
|
|||
|
||||
if (lineMessage != null)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
Console.WriteLine(lineMessage);
|
||||
}
|
||||
if (!player.RealPlayer)
|
||||
player.SendInfoMessage(lineMessage);
|
||||
else
|
||||
{
|
||||
player.SendMessage(lineMessage, lineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,26 +202,18 @@ namespace TShockAPI
|
|||
{
|
||||
if (settings.NothingToDisplayString != null)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
if (!player.RealPlayer)
|
||||
player.SendSuccessMessage(settings.NothingToDisplayString);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendMessage(settings.NothingToDisplayString, settings.HeaderTextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (settings.IncludeFooter && pageNumber + 1 <= pageCount)
|
||||
{
|
||||
if (player is TSServerPlayer)
|
||||
{
|
||||
if (!player.RealPlayer)
|
||||
player.SendInfoMessage(string.Format(settings.FooterFormat, pageNumber + 1, pageNumber, pageCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
player.SendMessage(string.Format(settings.FooterFormat, pageNumber + 1, pageNumber, pageCount), settings.FooterTextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,11 +222,11 @@ namespace TShockAPI
|
|||
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)
|
||||
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)
|
||||
|
|
@ -254,9 +237,7 @@ namespace TShockAPI
|
|||
{
|
||||
try
|
||||
{
|
||||
termString = termFormatter(term);
|
||||
|
||||
if (termString == null)
|
||||
if ((termString = termFormatter(term)) == null)
|
||||
continue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -270,41 +251,35 @@ namespace TShockAPI
|
|||
termString = term.ToString();
|
||||
}
|
||||
|
||||
bool goesOnNextLine = (lineBuilder.Length + termString.Length > maxCharsPerLine);
|
||||
if (!goesOnNextLine)
|
||||
if (lineBuilder.Length + termString.Length + separator.Length < maxCharsPerLine)
|
||||
{
|
||||
if (lineBuilder.Length > 0)
|
||||
lineBuilder.Append(separator);
|
||||
lineBuilder.Append(termString);
|
||||
lineBuilder.Append(termString).Append(separator);
|
||||
}
|
||||
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);
|
||||
lineBuilder.Clear().Append(termString).Append(separator);
|
||||
}
|
||||
}
|
||||
if (lineBuilder.Length > 0)
|
||||
lines.Add(lineBuilder.ToString());
|
||||
|
||||
if (lineBuilder.Length > 0)
|
||||
{
|
||||
lines.Add(lineBuilder.ToString().Substring(0, lineBuilder.Length - separator.Length));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
public static bool TryParsePageNumber(
|
||||
List<string> commandParameters, int expectedParamterIndex, TSPlayer errorMessageReceiver, out int pageNumber)
|
||||
public static bool TryParsePageNumber(List<string> commandParameters, int expectedParameterIndex, TSPlayer errorMessageReceiver, out int pageNumber)
|
||||
{
|
||||
pageNumber = 1;
|
||||
if (commandParameters.Count <= expectedParamterIndex)
|
||||
if (commandParameters.Count <= expectedParameterIndex)
|
||||
return true;
|
||||
|
||||
string pageNumberRaw = commandParameters[expectedParamterIndex];
|
||||
string pageNumberRaw = commandParameters[expectedParameterIndex];
|
||||
if (!int.TryParse(pageNumberRaw, out pageNumber) || pageNumber < 1)
|
||||
{
|
||||
if (errorMessageReceiver != null)
|
||||
errorMessageReceiver.SendErrorMessage(string.Format("\"{0}\" is not a valid page number.", pageNumberRaw));
|
||||
errorMessageReceiver.SendErrorMessage("\"{0}\" is not a valid page number.", pageNumberRaw);
|
||||
|
||||
pageNumber = 1;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ namespace TShockAPI
|
|||
|
||||
// tshock.admin nodes
|
||||
|
||||
[Description("User can set build protection status.")]
|
||||
public static readonly string antibuild = "tshock.admin.antibuild";
|
||||
|
||||
[Description("Prevents you from being kicked.")]
|
||||
public static readonly string immunetokick = "tshock.admin.nokick";
|
||||
|
||||
|
|
@ -74,7 +77,7 @@ namespace TShockAPI
|
|||
public static readonly string seeids = "tshock.admin.seeplayerids";
|
||||
|
||||
[Description("User can save all the players SSI state.")]
|
||||
public static readonly string savessi = "tshock.admin.savessi";
|
||||
public static readonly string savessc = "tshock.admin.savessi";
|
||||
|
||||
[Description("User can elevate other users' groups temporarily.")]
|
||||
public static readonly string settempgroup = "tshock.admin.tempgroup";
|
||||
|
|
@ -107,12 +110,6 @@ namespace TShockAPI
|
|||
[Description("User can reload the configurations file.")]
|
||||
public static readonly string cfgreload = "tshock.cfg.reload";
|
||||
|
||||
[Description("User can edit the max spawns.")]
|
||||
public static readonly string cfgmaxspawns = "tshock.cfg.maxspawns";
|
||||
|
||||
[Description("User can edit the spawnrate.")]
|
||||
public static readonly string cfgspawnrate = "tshock.cfg.spawnrate";
|
||||
|
||||
[Description("User can download updates to plugins that are currently running.")]
|
||||
public static readonly string updateplugins = "tshock.cfg.updateplugins";
|
||||
|
||||
|
|
@ -130,15 +127,15 @@ namespace TShockAPI
|
|||
[Description("Prevents you from being disabled by projectile abuse detection.")]
|
||||
public static readonly string ignoreprojectiledetection = "tshock.ignore.projectile";
|
||||
|
||||
[Description("Prevents you from being disabled by paint abuse detection.")]
|
||||
public static readonly string ignorepaintdetection = "tshock.ignore.paint";
|
||||
|
||||
[Description("Prevents you from being reverted by no clip detection.")]
|
||||
public static readonly string ignorenoclipdetection = "tshock.ignore.noclip";
|
||||
|
||||
[Description("Prevents you from being disabled by stack hack detection.")]
|
||||
public static readonly string ignorestackhackdetection = "tshock.ignore.itemstack";
|
||||
|
||||
[Description("Prevents you from being kicked by hacked health detection.")]
|
||||
public static readonly string ignorestathackdetection = "tshock.ignore.stats";
|
||||
|
||||
[Description("Prevents your actions from being ignored if damage is too high.")]
|
||||
public static readonly string ignoredamagecap = "tshock.ignore.damage";
|
||||
|
||||
|
|
@ -148,19 +145,28 @@ namespace TShockAPI
|
|||
[Description("Allow unrestricted SendTileSquare usage, for client side world editing.")]
|
||||
public static readonly string allowclientsideworldedit = "tshock.ignore.sendtilesquare";
|
||||
|
||||
[Description("Allow dropping banned items without the item being eaten.")]
|
||||
public static readonly string allowdroppingbanneditems = "tshock.ignore.dropbanneditem";
|
||||
|
||||
// tshock.item nodes
|
||||
|
||||
[Description("User can spawn items.")]
|
||||
public static readonly string item = "tshock.item.spawn";
|
||||
|
||||
[Description("User can clear items.")]
|
||||
public static readonly string clearitems = "tshock.item.clear";
|
||||
|
||||
[Description("Allows you to use banned items.")]
|
||||
public static readonly string usebanneditem = "tshock.item.usebanned";
|
||||
|
||||
// tshock.npc nodes
|
||||
|
||||
[Description("User can edit the max spawns.")]
|
||||
public static readonly string maxspawns = "tshock.npc.maxspawns";
|
||||
|
||||
[Description("User can edit the spawnrate.")]
|
||||
public static readonly string spawnrate = "tshock.npc.spawnrate";
|
||||
|
||||
[Description("User can start an invasion.")]
|
||||
public static readonly string invade = "tshock.npc.invade";
|
||||
|
||||
[Description("User can spawn bosses.")]
|
||||
public static readonly string spawnboss = "tshock.npc.spawnboss";
|
||||
|
||||
|
|
@ -207,13 +213,28 @@ namespace TShockAPI
|
|||
[Description("User can use /spawn.")]
|
||||
public static readonly string spawn = "tshock.tp.spawn";
|
||||
|
||||
[Description("User can use the Rod of Discor.")]
|
||||
public static readonly string rod = "tshock.tp.rod";
|
||||
|
||||
// tshock.world nodes
|
||||
|
||||
[Description("Allows you to edit the spawn.")]
|
||||
public static readonly string editspawn = "tshock.world.editspawn";
|
||||
|
||||
[Description("Allows you to edit regions.")]
|
||||
public static readonly string editregion = "tshock.world.editregion";
|
||||
|
||||
[Description("User can force a blood moon.")]
|
||||
public static readonly string bloodmoon = "tshock.world.time.bloodmoon";
|
||||
|
||||
[Description("User can force a pumpkin moon.")]
|
||||
public static readonly string pumpkinmoon = "tshock.world.time.pumpkinmoon";
|
||||
|
||||
[Description("User can force a snow moon.")]
|
||||
public static readonly string snowmoon = "tshock.world.time.snowmoon";
|
||||
|
||||
[Description("User can set the time.")]
|
||||
public static readonly string time = "tshock.world.settime";
|
||||
public static readonly string time = "tshock.world.time.set";
|
||||
|
||||
[Description("User can grow plants.")]
|
||||
public static readonly string grow = "tshock.world.grow";
|
||||
|
|
@ -242,14 +263,29 @@ namespace TShockAPI
|
|||
[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 drop a meteor.")]
|
||||
public static readonly string dropmeteor = "tshock.world.time.dropmeteor";
|
||||
|
||||
[Description("User can force an eclipse.")]
|
||||
public static readonly string eclipse = "tshock.world.time.eclipse";
|
||||
|
||||
[Description("User can force a full moon.")]
|
||||
public static readonly string fullmoon = "tshock.world.time.fullmoon";
|
||||
|
||||
[Description("User can modify the world.")]
|
||||
public static readonly string canbuild = "tshock.world.modify";
|
||||
|
||||
[Description("User can paint tiles.")]
|
||||
public static readonly string canpaint = "tshock.world.paint";
|
||||
|
||||
[Description("User can turn on or off the rain.")]
|
||||
public static readonly string rain = "tshock.world.rain";
|
||||
|
||||
// Non-grouped
|
||||
|
||||
[Description("User can clear items or projectiles.")]
|
||||
public static readonly string clear = "tshock.clear";
|
||||
|
||||
[Description("User can kill others.")]
|
||||
public static readonly string kill = "tshock.kill";
|
||||
|
||||
|
|
@ -280,6 +316,12 @@ namespace TShockAPI
|
|||
[Description("User can get the server info.")]
|
||||
public static readonly string serverinfo = "tshock.info";
|
||||
|
||||
[Description("Player recovers health as damage is taken. Can be one shotted.")]
|
||||
public static readonly string godmode = "tshock.godmode";
|
||||
|
||||
[Description("Player can chat")]
|
||||
public static readonly string canchat = "tshock.canchat";
|
||||
|
||||
/// <summary>
|
||||
/// Lists all commands associated with a given permission
|
||||
/// </summary>
|
||||
|
|
@ -300,7 +342,7 @@ namespace TShockAPI
|
|||
var sb = new StringBuilder();
|
||||
foreach (var field in typeof(Permissions).GetFields().OrderBy(f => f.Name))
|
||||
{
|
||||
var name = field.Name;
|
||||
var name = (string)field.GetValue(null);
|
||||
|
||||
var descattr =
|
||||
field.GetCustomAttributes(false).FirstOrDefault(o => o is DescriptionAttribute) as DescriptionAttribute;
|
||||
|
|
@ -319,9 +361,9 @@ namespace TShockAPI
|
|||
c =>
|
||||
c.Name + (c.Names.Count > 1 ? "({0})".SFormat(string.Join(" ", c.Names.ToArray(), 1, c.Names.Count - 1)) : ""));
|
||||
|
||||
sb.AppendLine("## <a id=\"{0}\">{0}</a> ".SFormat(name));
|
||||
sb.AppendLine("**Description:** {0} ".SFormat(desc));
|
||||
sb.AppendLine("**Commands:** {0} ".SFormat(strs.Count() > 0 ? string.Join(" ", strs) : "None"));
|
||||
sb.AppendLine("{0}".SFormat(name));
|
||||
sb.AppendLine("Description: {0} ".SFormat(desc));
|
||||
sb.AppendLine("Commands: {0} ".SFormat(strs.Count() > 0 ? string.Join(" ", strs) : "None"));
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
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 = "";
|
||||
}
|
||||
}
|
||||
|
|
@ -49,5 +49,5 @@ using System.Runtime.InteropServices;
|
|||
// Build Number
|
||||
// MMdd of the build
|
||||
|
||||
[assembly: AssemblyVersion("4.1.0.0926")]
|
||||
[assembly: AssemblyFileVersion("4.1.0.0926")]
|
||||
[assembly: AssemblyVersion("4.2.2.1228")]
|
||||
[assembly: AssemblyFileVersion("4.2.2.1228")]
|
||||
|
|
|
|||
38
TShockAPI/RaptorPacketTypes.cs
Normal file
38
TShockAPI/RaptorPacketTypes.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom packet types for use with Raptor.
|
||||
/// </summary>
|
||||
public enum RaptorPacketTypes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// The packet sent to the server to be acknowledged as a Raptor client.
|
||||
/// </summary>
|
||||
Acknowledge = 0,
|
||||
/// <summary>
|
||||
/// The packet sent to the client which dictates its permissions.
|
||||
/// </summary>
|
||||
Permissions,
|
||||
/// <summary>
|
||||
/// The packet sent which sets region info.
|
||||
/// </summary>
|
||||
Region,
|
||||
/// <summary>
|
||||
/// The packet sent to delete a region.
|
||||
/// </summary>
|
||||
RegionDelete,
|
||||
/// <summary>
|
||||
/// The packet sent which sets warp info.
|
||||
/// </summary>
|
||||
Warp,
|
||||
/// <summary>
|
||||
/// The packet sent to delete a warp.
|
||||
/// </summary>
|
||||
WarpDelete
|
||||
}
|
||||
}
|
||||
68
TShockAPI/Resources.Designer.cs
generated
68
TShockAPI/Resources.Designer.cs
generated
|
|
@ -1,25 +1,7 @@
|
|||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.235
|
||||
// Runtime Version:4.0.30319.17929
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
|
|
@ -27,6 +9,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TShockAPI {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
|
|
@ -74,48 +59,5 @@ namespace TShockAPI {
|
|||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to #Format
|
||||
///#name parent permisson1 permission2 permissionN
|
||||
///#if there is no parent, put null instead
|
||||
///#groups inherit permissions from their parents
|
||||
///#put a ! before a permission to negate it
|
||||
///#Do not remove the group default
|
||||
///#Do not name a group SuperAdmin, that is hard-coded into the code, it grants total permissions
|
||||
///#ALWAYS DECLARE A GROUP'S PARENT BEFORE YOU DECLARE THE GROUP
|
||||
///
|
||||
///#currently avaliable permissions:
|
||||
///#reservedslot - reserved slot for player
|
||||
///#canwater - allow players to use water
|
||||
///#canlav [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string groups {
|
||||
get {
|
||||
return ResourceManager.GetString("groups", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to #see https://github.com/TShock/TShock/wiki/Item-List for a list of item ids
|
||||
///#List each banned item ID below this, with each on a new line.
|
||||
/// </summary>
|
||||
internal static string itembans {
|
||||
get {
|
||||
return ResourceManager.GetString("itembans", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to #format
|
||||
///#ip group
|
||||
///#see groups.txt for a list of groups
|
||||
///#127.0.0.1 superadmin.
|
||||
/// </summary>
|
||||
internal static string users {
|
||||
get {
|
||||
return ResourceManager.GetString("users", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,13 +118,4 @@
|
|||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="groups" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>config\groups.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
<data name="itembans" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>config\itembans.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||
</data>
|
||||
<data name="users" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>config\users.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -196,8 +196,10 @@ namespace Rests
|
|||
protected virtual object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
||||
{
|
||||
object result = cmd.Execute(verbs, parms);
|
||||
if (cmd.DoLog)
|
||||
if (cmd.DoLog && TShock.Config.LogRest)
|
||||
{
|
||||
Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace TShockAPI
|
|||
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("/status", (a, b) => this.ServerStatus(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)));
|
||||
}
|
||||
|
|
@ -236,7 +236,7 @@ namespace TShockAPI
|
|||
var players = new ArrayList();
|
||||
foreach (TSPlayer tsPlayer in TShock.Players.Where(p => null != p))
|
||||
{
|
||||
var p = PlayerFilter(tsPlayer, parameters);
|
||||
var p = PlayerFilter(tsPlayer, parameters, ((tokenData.UserGroupName) != "" && TShock.Utils.GetGroup(tokenData.UserGroupName).HasPermission(RestPermissions.viewips)));
|
||||
if (null != p)
|
||||
players.Add(p);
|
||||
}
|
||||
|
|
@ -258,7 +258,7 @@ namespace TShockAPI
|
|||
rules.Add("PvPMode", TShock.Config.PvPMode);
|
||||
rules.Add("SpawnProtection", TShock.Config.SpawnProtection);
|
||||
rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius);
|
||||
rules.Add("ServerSideInventory", TShock.Config.ServerSideInventory);
|
||||
rules.Add("ServerSideInventory", TShock.Config.ServerSideCharacter);
|
||||
|
||||
ret.Add("rules", rules);
|
||||
}
|
||||
|
|
@ -307,7 +307,7 @@ namespace TShockAPI
|
|||
return RestMissingParam("password");
|
||||
|
||||
// NOTE: ip can be blank
|
||||
User user = new User(username, password, group, "", "");
|
||||
User user = new User(username, password, "", group, "", "", "");
|
||||
try
|
||||
{
|
||||
TShock.Users.AddUser(user);
|
||||
|
|
@ -404,7 +404,7 @@ namespace TShockAPI
|
|||
|
||||
try
|
||||
{
|
||||
TShock.Bans.AddBan(ip, name, parameters["reason"], true, tokenData.Username);
|
||||
TShock.Bans.AddBan(ip, name, "", parameters["reason"], true, tokenData.Username);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -622,7 +622,7 @@ namespace TShockAPI
|
|||
|
||||
TSPlayer player = (TSPlayer)ret;
|
||||
var reason = null == parameters["reason"] ? "Banned via web" : parameters["reason"];
|
||||
TShock.Bans.AddBan(player.IP, player.Name, reason);
|
||||
TShock.Bans.AddBan(player.IP, player.Name, "", reason);
|
||||
TShock.Utils.ForceKick(player, reason, false, true);
|
||||
return RestResponse("Player " + player.Name + " was banned");
|
||||
}
|
||||
|
|
@ -719,7 +719,7 @@ namespace TShockAPI
|
|||
var permissions = (null == parameters["permissions"]) ? group.Permissions : parameters["permissions"];
|
||||
try
|
||||
{
|
||||
TShock.Groups.UpdateGroup(group.Name, parent, permissions, chatcolor);
|
||||
TShock.Groups.UpdateGroup(group.Name, parent, permissions, chatcolor, group.Suffix, group.Prefix);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -859,18 +859,22 @@ namespace TShockAPI
|
|||
return group;
|
||||
}
|
||||
|
||||
private Dictionary<string, object> PlayerFilter(TSPlayer tsPlayer, IParameterCollection parameters)
|
||||
private Dictionary<string, object> PlayerFilter(TSPlayer tsPlayer, IParameterCollection parameters, bool viewips = false)
|
||||
{
|
||||
var player = new Dictionary<string, object>
|
||||
{
|
||||
{"nickname", tsPlayer.Name},
|
||||
{"username", null == tsPlayer.UserAccountName ? "" : tsPlayer.UserAccountName},
|
||||
{"ip", tsPlayer.IP},
|
||||
{"username", tsPlayer.UserAccountName ?? ""},
|
||||
{"group", tsPlayer.Group.Name},
|
||||
{"active", tsPlayer.Active},
|
||||
{"state", tsPlayer.State},
|
||||
{"team", tsPlayer.Team},
|
||||
};
|
||||
|
||||
if (viewips)
|
||||
{
|
||||
player.Add("ip", tsPlayer.IP);
|
||||
}
|
||||
foreach (IParameter filter in parameters)
|
||||
{
|
||||
if (player.ContainsKey(filter.Name) && !player[filter.Name].Equals(filter.Value))
|
||||
|
|
|
|||
|
|
@ -83,5 +83,8 @@ namespace Rests
|
|||
|
||||
[Description("REST user can run raw TShock commands (the raw command permissions are also checked though).")]
|
||||
public static readonly string restrawcommand = "tshock.rest.command";
|
||||
|
||||
[Description("REST user can view the ips of players.")]
|
||||
public static readonly string viewips = "tshock.rest.viewips";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ namespace Rests
|
|||
}
|
||||
|
||||
object result = secureCmd.Execute(verbs, parms, tokenData);
|
||||
if (cmd.DoLog)
|
||||
if (cmd.DoLog && TShock.Config.LogRest)
|
||||
TShock.Utils.SendLogs(string.Format(
|
||||
"\"{0}\" requested REST endpoint: {1}", tokenData.Username, this.BuildRequestUri(cmd, verbs, parms, false)),
|
||||
Color.PaleVioletRed);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using Terraria;
|
||||
using TerrariaApi.Server;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
|
|
@ -45,18 +46,21 @@ namespace TShockAPI
|
|||
/// <summary>
|
||||
/// SaveWorld event handler which notifies users that the server may lag
|
||||
/// </summary>
|
||||
public void OnSaveWorld(bool resettime = false, HandledEventArgs e = null)
|
||||
public void OnSaveWorld(WorldSaveEventArgs args)
|
||||
{
|
||||
// Protect against internal errors causing save failures
|
||||
// These can be caused by an unexpected error such as a bad or out of date plugin
|
||||
try
|
||||
if (TShock.Config.AnnounceSave)
|
||||
{
|
||||
TShock.Utils.Broadcast("Saving world. Momentary lag might result from this.", Color.Red);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("World saved notification failed");
|
||||
Log.Error(ex.ToString());
|
||||
// Protect against internal errors causing save failures
|
||||
// These can be caused by an unexpected error such as a bad or out of date plugin
|
||||
try
|
||||
{
|
||||
TShock.Utils.Broadcast("Saving world. Momentary lag might result from this.", Color.Red);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("World saved notification failed");
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +124,7 @@ namespace TShockAPI
|
|||
{
|
||||
if (task.direct)
|
||||
{
|
||||
OnSaveWorld();
|
||||
OnSaveWorld(new WorldSaveEventArgs());
|
||||
WorldGen.realsaveWorld(task.resetTime);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
101
TShockAPI/StatTracker.cs
Normal file
101
TShockAPI/StatTracker.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
public class StatTracker
|
||||
{
|
||||
private bool failed;
|
||||
private bool initialized;
|
||||
public StatTracker()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = true;
|
||||
ThreadPool.QueueUserWorkItem(SendUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
private HttpWebResponse GetResponseNoException(HttpWebRequest req)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (HttpWebResponse)req.GetResponse();
|
||||
}
|
||||
catch (WebException we)
|
||||
{
|
||||
var resp = we.Response as HttpWebResponse;
|
||||
if (resp == null)
|
||||
throw;
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
|
||||
private void SendUpdate(object info)
|
||||
{
|
||||
Thread.Sleep(1000*60*15);
|
||||
var data = new JsonData
|
||||
{
|
||||
port = Terraria.Netplay.serverPort,
|
||||
currentPlayers = TShock.Utils.ActivePlayers(),
|
||||
maxPlayers = TShock.Config.MaxSlots,
|
||||
systemRam = 0,
|
||||
systemCPUClock = 0,
|
||||
version = TShock.VersionNum.ToString(),
|
||||
terrariaVersion = Terraria.Main.versionNumber2,
|
||||
mono = Terraria.Main.runningMono
|
||||
};
|
||||
|
||||
var serialized = Newtonsoft.Json.JsonConvert.SerializeObject(data);
|
||||
var encoded = HttpUtility.UrlEncode(serialized);
|
||||
var uri = String.Format("http://96.47.231.227:8000?data={0}", encoded);
|
||||
var client = (HttpWebRequest)WebRequest.Create(uri);
|
||||
client.Timeout = 5000;
|
||||
try
|
||||
{
|
||||
using (var resp = GetResponseNoException(client))
|
||||
{
|
||||
if (resp.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new IOException("Server did not respond with an OK.");
|
||||
}
|
||||
|
||||
failed = false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!failed)
|
||||
{
|
||||
Log.ConsoleError("StatTracker Exception: {0}", e);
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool.QueueUserWorkItem(SendUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
public struct JsonData
|
||||
{
|
||||
public int port;
|
||||
public int currentPlayers;
|
||||
public int maxPlayers;
|
||||
public int systemRam;
|
||||
public int systemCPUClock;
|
||||
public string version;
|
||||
public string terrariaVersion;
|
||||
public bool mono;
|
||||
}
|
||||
}
|
||||
729
TShockAPI/TSPlayer.cs
Normal file → Executable file
729
TShockAPI/TSPlayer.cs
Normal file → Executable file
|
|
@ -20,8 +20,10 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Terraria;
|
||||
using TShockAPI.DB;
|
||||
using TShockAPI.Net;
|
||||
|
||||
namespace TShockAPI
|
||||
|
|
@ -38,6 +40,11 @@ namespace TShockAPI
|
|||
/// </summary>
|
||||
public static readonly TSPlayer All = new TSPlayer("All");
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the player is using Raptor.
|
||||
/// </summary>
|
||||
public bool IsRaptor { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of tiles that the player has killed in the last second.
|
||||
/// </summary>
|
||||
|
|
@ -49,24 +56,44 @@ namespace TShockAPI
|
|||
public int TilePlaceThreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of liquid( in tiles ) that the player has placed in the last second.
|
||||
/// The amount of liquid (in tiles) that the player has placed in the last second.
|
||||
/// </summary>
|
||||
public int TileLiquidThreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of tiles that the player has painted in the last second.
|
||||
/// </summary>
|
||||
public int PaintThreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of projectiles created by the player in the last second.
|
||||
/// </summary>
|
||||
public int ProjectileThreshold { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A timer to keep track of whether or not the player has recently thrown an explosive
|
||||
/// </summary>
|
||||
public int RecentFuse = 0;
|
||||
|
||||
/// <summary>
|
||||
/// A system to delay Remembered Position Teleports a few seconds
|
||||
/// </summary>
|
||||
|
||||
public int RPPending = 0;
|
||||
|
||||
public int sX = -1;
|
||||
public int sY = -1;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A queue of tiles destroyed by the player for reverting.
|
||||
/// </summary>
|
||||
public Dictionary<Vector2, TileData> TilesDestroyed { get; protected set; }
|
||||
public Dictionary<Vector2, Tile> TilesDestroyed { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// A queue of tiles placed by the player for reverting.
|
||||
/// </summary>
|
||||
public Dictionary<Vector2, TileData> TilesCreated { get; protected set; }
|
||||
public Dictionary<Vector2, Tile> TilesCreated { get; protected set; }
|
||||
|
||||
public int FirstMaxHP { get; set; }
|
||||
|
||||
|
|
@ -103,7 +130,7 @@ namespace TShockAPI
|
|||
/// <summary>
|
||||
/// The last time the player changed their team or pvp status.
|
||||
/// </summary>
|
||||
public DateTime LastPvpChange;
|
||||
public DateTime LastPvPTeamChange;
|
||||
|
||||
/// <summary>
|
||||
/// Temp points for use in regions and other plugins.
|
||||
|
|
@ -129,11 +156,6 @@ namespace TShockAPI
|
|||
/// </summary>
|
||||
public DateTime LastThreat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Not used, can be removed.
|
||||
/// </summary>
|
||||
public DateTime LastTileChangeNotify { get; set; }
|
||||
|
||||
public bool InitSpawn;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -141,10 +163,8 @@ namespace TShockAPI
|
|||
/// </summary>
|
||||
public bool DisplayLogs = true;
|
||||
|
||||
public Vector2 oldSpawn = Vector2.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The last player that the player whispered with( to or from ).
|
||||
/// The last player that the player whispered with (to or from).
|
||||
/// </summary>
|
||||
public TSPlayer LastWhisper;
|
||||
|
||||
|
|
@ -195,8 +215,6 @@ namespace TShockAPI
|
|||
/// </summary>
|
||||
public bool mute;
|
||||
|
||||
public bool TpLock;
|
||||
|
||||
private Player FakePlayer;
|
||||
|
||||
public bool RequestedSection;
|
||||
|
|
@ -277,6 +295,21 @@ namespace TShockAPI
|
|||
/// </summary>
|
||||
public bool LoginHarassed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Player cant die, unless onehit
|
||||
/// </summary>
|
||||
public bool GodMode = false;
|
||||
|
||||
/// <summary>
|
||||
/// Players controls are inverted if using SSC
|
||||
/// </summary>
|
||||
public bool Confused = false;
|
||||
|
||||
/// <summary>
|
||||
/// The last projectile type this player tried to kill.
|
||||
/// </summary>
|
||||
public int LastKilledProjectile = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the player is a real, human, player on the server.
|
||||
/// </summary>
|
||||
|
|
@ -294,12 +327,31 @@ namespace TShockAPI
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player's selected item.
|
||||
/// </summary>
|
||||
public Item SelectedItem
|
||||
{
|
||||
get { return TPlayer.inventory[TPlayer.selectedItem]; }
|
||||
}
|
||||
|
||||
public int State
|
||||
{
|
||||
get { return Netplay.serverSock[Index].state; }
|
||||
set { Netplay.serverSock[Index].state = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player's UUID.
|
||||
/// </summary>
|
||||
public string UUID
|
||||
{
|
||||
get { return RealPlayer ? Netplay.serverSock[Index].clientUUID : ""; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the player's IP.
|
||||
/// </summary>
|
||||
public string IP
|
||||
{
|
||||
get
|
||||
|
|
@ -321,16 +373,16 @@ namespace TShockAPI
|
|||
/// Saves the player's inventory to SSI
|
||||
/// </summary>
|
||||
/// <returns>bool - True/false if it saved successfully</returns>
|
||||
public bool SaveServerInventory()
|
||||
public bool SaveServerCharacter()
|
||||
{
|
||||
if (!TShock.Config.ServerSideInventory)
|
||||
if (!TShock.Config.ServerSideCharacter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
PlayerData.CopyInventory(this);
|
||||
TShock.InventoryDB.InsertPlayerData(this);
|
||||
PlayerData.CopyCharacter(this);
|
||||
TShock.CharacterDB.InsertPlayerData(this);
|
||||
return true;
|
||||
} catch (Exception e)
|
||||
{
|
||||
|
|
@ -340,6 +392,29 @@ namespace TShockAPI
|
|||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the players server side character to client
|
||||
/// </summary>
|
||||
/// <returns>bool - True/false if it saved successfully</returns>
|
||||
public bool SendServerCharacter()
|
||||
{
|
||||
if (!TShock.Config.ServerSideCharacter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
PlayerData.RestoreCharacter(this);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terraria Player
|
||||
/// </summary>
|
||||
|
|
@ -383,6 +458,8 @@ namespace TShockAPI
|
|||
get { return (int) (Y/16); }
|
||||
}
|
||||
|
||||
public bool TpLock;
|
||||
|
||||
public bool InventorySlotAvailable
|
||||
{
|
||||
get
|
||||
|
|
@ -390,7 +467,7 @@ namespace TShockAPI
|
|||
bool flag = false;
|
||||
if (RealPlayer)
|
||||
{
|
||||
for (int i = 0; i < 40; i++) //41 is trash can, 42-45 is coins, 46-49 is ammo
|
||||
for (int i = 0; i < 50; i++) //51 is trash can, 52-55 is coins, 56-59 is ammo
|
||||
{
|
||||
if (TPlayer.inventory[i] == null || !TPlayer.inventory[i].active || TPlayer.inventory[i].name == "")
|
||||
{
|
||||
|
|
@ -405,8 +482,8 @@ namespace TShockAPI
|
|||
|
||||
public TSPlayer(int index)
|
||||
{
|
||||
TilesDestroyed = new Dictionary<Vector2, TileData>();
|
||||
TilesCreated = new Dictionary<Vector2, TileData>();
|
||||
TilesDestroyed = new Dictionary<Vector2, Tile>();
|
||||
TilesCreated = new Dictionary<Vector2, Tile>();
|
||||
Index = index;
|
||||
Group = Group.DefaultGroup;
|
||||
IceTiles = new List<Point>();
|
||||
|
|
@ -415,8 +492,8 @@ namespace TShockAPI
|
|||
|
||||
protected TSPlayer(String playerName)
|
||||
{
|
||||
TilesDestroyed = new Dictionary<Vector2, TileData>();
|
||||
TilesCreated = new Dictionary<Vector2, TileData>();
|
||||
TilesDestroyed = new Dictionary<Vector2, Tile>();
|
||||
TilesCreated = new Dictionary<Vector2, Tile>();
|
||||
Index = -1;
|
||||
FakePlayer = new Player {name = playerName, whoAmi = -1};
|
||||
Group = Group.DefaultGroup;
|
||||
|
|
@ -457,12 +534,49 @@ namespace TShockAPI
|
|||
//Sending a fake world id causes the client to not be able to find a stored spawnx/y.
|
||||
//This fixes the bed spawn point bug. With a fake world id it wont be able to find the bed spawn.
|
||||
WorldID = !fakeid ? Main.worldID : -1,
|
||||
WorldFlags = (WorldGen.shadowOrbSmashed ? WorldInfoFlag.OrbSmashed : WorldInfoFlag.None) |
|
||||
(NPC.downedBoss1 ? WorldInfoFlag.DownedBoss1 : WorldInfoFlag.None) |
|
||||
(NPC.downedBoss2 ? WorldInfoFlag.DownedBoss2 : WorldInfoFlag.None) |
|
||||
(NPC.downedBoss3 ? WorldInfoFlag.DownedBoss3 : WorldInfoFlag.None) |
|
||||
(Main.hardMode ? WorldInfoFlag.HardMode : WorldInfoFlag.None) |
|
||||
(NPC.downedClown ? WorldInfoFlag.DownedClown : WorldInfoFlag.None),
|
||||
MoonType = (byte)Main.moonType,
|
||||
TreeX0 = Main.treeX[0],
|
||||
TreeX1 = Main.treeX[1],
|
||||
TreeX2 = Main.treeX[2],
|
||||
TreeStyle0 = (byte)Main.treeStyle[0],
|
||||
TreeStyle1 = (byte)Main.treeStyle[1],
|
||||
TreeStyle2 = (byte)Main.treeStyle[2],
|
||||
TreeStyle3 = (byte)Main.treeStyle[3],
|
||||
CaveBackX0 = Main.caveBackX[0],
|
||||
CaveBackX1 = Main.caveBackX[1],
|
||||
CaveBackX2 = Main.caveBackX[2],
|
||||
CaveBackStyle0 = (byte)Main.caveBackStyle[0],
|
||||
CaveBackStyle1 = (byte)Main.caveBackStyle[1],
|
||||
CaveBackStyle2 = (byte)Main.caveBackStyle[2],
|
||||
CaveBackStyle3 = (byte)Main.caveBackStyle[3],
|
||||
SetBG0 = (byte)WorldGen.treeBG,
|
||||
SetBG1 = (byte)WorldGen.corruptBG,
|
||||
SetBG2 = (byte)WorldGen.jungleBG,
|
||||
SetBG3 = (byte)WorldGen.snowBG,
|
||||
SetBG4 = (byte)WorldGen.hallowBG,
|
||||
SetBG5 = (byte)WorldGen.crimsonBG,
|
||||
SetBG6 = (byte)WorldGen.desertBG,
|
||||
SetBG7 = (byte)WorldGen.oceanBG,
|
||||
IceBackStyle = (byte)Main.iceBackStyle,
|
||||
JungleBackStyle = (byte)Main.jungleBackStyle,
|
||||
HellBackStyle = (byte)Main.hellBackStyle,
|
||||
WindSpeed = Main.windSpeed,
|
||||
NumberOfClouds = (byte)Main.numClouds,
|
||||
BossFlags = (WorldGen.shadowOrbSmashed ? BossFlags.OrbSmashed : BossFlags.None) |
|
||||
(NPC.downedBoss1 ? BossFlags.DownedBoss1 : BossFlags.None) |
|
||||
(NPC.downedBoss2 ? BossFlags.DownedBoss2 : BossFlags.None) |
|
||||
(NPC.downedBoss3 ? BossFlags.DownedBoss3 : BossFlags.None) |
|
||||
(Main.hardMode ? BossFlags.HardMode : BossFlags.None) |
|
||||
(NPC.downedClown ? BossFlags.DownedClown : BossFlags.None) |
|
||||
(Main.ServerSideCharacter ? BossFlags.ServerSideCharacter : BossFlags.None),
|
||||
BossFlags2 = (NPC.downedMechBoss1 ? BossFlags2.DownedMechBoss1 : BossFlags2.None) |
|
||||
(NPC.downedMechBoss2 ? BossFlags2.DownedMechBoss2 : BossFlags2.None) |
|
||||
(NPC.downedMechBoss3 ? BossFlags2.DownedMechBoss3 : BossFlags2.None) |
|
||||
(NPC.downedMechBossAny ? BossFlags2.DownedMechBossAny : BossFlags2.None) |
|
||||
(Main.cloudBGActive == 1f ? BossFlags2.CloudBg : BossFlags2.None) |
|
||||
(WorldGen.crimson ? BossFlags2.Crimson : BossFlags2.None) |
|
||||
(Main.pumpkinMoon ? BossFlags2.Pumpkin : BossFlags2.None),
|
||||
Rain = Main.maxRaining,
|
||||
WorldName = TShock.Config.UseServerName ? TShock.Config.ServerName : Main.worldName
|
||||
};
|
||||
msg.PackFull(ms);
|
||||
|
|
@ -470,44 +584,47 @@ namespace TShockAPI
|
|||
}
|
||||
}
|
||||
|
||||
public bool Teleport(int tilex, int tiley)
|
||||
public bool Teleport(float x, float y, byte style = 1)
|
||||
{
|
||||
InitSpawn = false;
|
||||
|
||||
SendWorldInfo(tilex, tiley, true);
|
||||
|
||||
//150 Should avoid all client crash errors
|
||||
//The error occurs when a tile trys to update which the client hasnt load yet, Clients only update tiles withen 150 blocks
|
||||
//Try 300 if it does not work (Higher number - Longer load times - Less chance of error)
|
||||
//Should we properly send sections so that clients don't get tiles twice?
|
||||
SendTileSquare(tilex, tiley, 150);
|
||||
|
||||
/* //We shouldn't need this section anymore -it can prevent otherwise acceptable teleportation under some circumstances.
|
||||
|
||||
if (!SendTileSquare(tilex, tiley, 150))
|
||||
if (x > Main.rightWorld - 992)
|
||||
{
|
||||
InitSpawn = true;
|
||||
SendWorldInfo(Main.spawnTileX, Main.spawnTileY, false);
|
||||
return false;
|
||||
x = Main.rightWorld - 992;
|
||||
}
|
||||
if (x < 992)
|
||||
{
|
||||
x = 992;
|
||||
}
|
||||
if (y > Main.bottomWorld - 992)
|
||||
{
|
||||
y = Main.bottomWorld - 992;
|
||||
}
|
||||
if (y < 992)
|
||||
{
|
||||
y = 992;
|
||||
}
|
||||
|
||||
*/
|
||||
Spawn(-1, -1);
|
||||
|
||||
SendWorldInfo(Main.spawnTileX, Main.spawnTileY, false);
|
||||
|
||||
TPlayer.position.X = (float)(tilex * 16 + 8 - TPlayer.width /2);
|
||||
TPlayer.position.Y = (float)(tiley * 16 - TPlayer.height);
|
||||
//We need to send the tile data again to prevent clients from thinking they *really* destroyed blocks just now.
|
||||
|
||||
SendTileSquare(tilex, tiley, 10);
|
||||
|
||||
SendTileSquare((int) (x/16), (int) (y/16), 15);
|
||||
TPlayer.Teleport(new Vector2(x, y), style);
|
||||
NetMessage.SendData((int)PacketTypes.Teleport, -1, -1, "", 0, TPlayer.whoAmi, x, y, style);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Spawn()
|
||||
public void Heal(int health = 500)
|
||||
{
|
||||
Spawn(TPlayer.SpawnX, TPlayer.SpawnY);
|
||||
NetMessage.SendData((int)PacketTypes.PlayerHealOther, -1, -1, "", this.TPlayer.whoAmi, health);
|
||||
}
|
||||
|
||||
public void Spawn()
|
||||
{
|
||||
// TPlayer.FindSpawn();
|
||||
if (this.sX > 0 && this.sY > 0)
|
||||
{
|
||||
Spawn(this.sX, this.sY);
|
||||
}
|
||||
else
|
||||
{
|
||||
Spawn(TPlayer.SpawnX, TPlayer.SpawnY);
|
||||
}
|
||||
}
|
||||
|
||||
public void Spawn(int tilex, int tiley)
|
||||
|
|
@ -541,45 +658,52 @@ namespace TShockAPI
|
|||
|
||||
public virtual bool SendTileSquare(int x, int y, int size = 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
int num = (size - 1)/2;
|
||||
int m_x=0;
|
||||
int m_y=0;
|
||||
try
|
||||
{
|
||||
int num = (size - 1)/2;
|
||||
int m_x = 0;
|
||||
int m_y = 0;
|
||||
|
||||
if (x - num <0){
|
||||
m_x=0;
|
||||
}else{
|
||||
m_x = x - num;
|
||||
}
|
||||
if (x - num < 0)
|
||||
{
|
||||
m_x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_x = x - num;
|
||||
}
|
||||
|
||||
if (y - num <0){
|
||||
m_y=0;
|
||||
}else{
|
||||
m_y = y - num;
|
||||
}
|
||||
if (y - num < 0)
|
||||
{
|
||||
m_y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_y = y - num;
|
||||
}
|
||||
|
||||
if (m_x + size > Main.maxTilesX){
|
||||
m_x=Main.maxTilesX - size;
|
||||
}
|
||||
if (m_x + size > Main.maxTilesX)
|
||||
{
|
||||
m_x = Main.maxTilesX - size;
|
||||
}
|
||||
|
||||
if (m_y + size > Main.maxTilesY){
|
||||
m_y=Main.maxTilesY - size;
|
||||
}
|
||||
if (m_y + size > Main.maxTilesY)
|
||||
{
|
||||
m_y = Main.maxTilesY - size;
|
||||
}
|
||||
|
||||
SendData(PacketTypes.TileSendSquare, "", size, m_x, m_y);
|
||||
return true;
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
|
||||
// This is expected if square exceeds array.
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
return false;
|
||||
SendData(PacketTypes.TileSendSquare, "", size, m_x, m_y);
|
||||
return true;
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
// This is expected if square exceeds array.
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool GiveItemCheck(int type, string name, int width, int height, int stack, int prefix = 0)
|
||||
|
|
@ -594,7 +718,7 @@ namespace TShockAPI
|
|||
|
||||
public virtual void GiveItem(int type, string name, int width, int height, int stack, int prefix = 0)
|
||||
{
|
||||
int itemid = Item.NewItem((int) X, (int) Y, width, height, type, stack, true, prefix);
|
||||
int itemid = Item.NewItem((int) X, (int) Y, width, height, type, stack, true, prefix, true);
|
||||
|
||||
// This is for special pickaxe/hammers/swords etc
|
||||
Main.item[itemid].SetDefaults(name);
|
||||
|
|
@ -604,8 +728,10 @@ namespace TShockAPI
|
|||
Main.item[itemid].stack = stack;
|
||||
Main.item[itemid].owner = Index;
|
||||
Main.item[itemid].prefix = (byte) prefix;
|
||||
NetMessage.SendData((int) PacketTypes.ItemDrop, -1, -1, "", itemid, 0f, 0f, 0f);
|
||||
NetMessage.SendData((int) PacketTypes.ItemOwner, -1, -1, "", itemid, 0f, 0f, 0f);
|
||||
Main.item[itemid].noGrabDelay = 1;
|
||||
Main.item[itemid].velocity = Main.player[this.Index].velocity;
|
||||
NetMessage.SendData((int)PacketTypes.ItemDrop, -1, -1, "", itemid, 0f, 0f, 0f);
|
||||
NetMessage.SendData((int)PacketTypes.ItemOwner, -1, -1, "", itemid, 0f, 0f, 0f);
|
||||
}
|
||||
|
||||
public virtual void SendInfoMessage(string msg)
|
||||
|
|
@ -681,15 +807,37 @@ namespace TShockAPI
|
|||
SendData(PacketTypes.PlayerTeam, "", Index);
|
||||
}
|
||||
|
||||
public virtual void Disable(string reason = "")
|
||||
private DateTime LastDisableNotification = DateTime.UtcNow;
|
||||
public int ActiveChest = -1;
|
||||
|
||||
public virtual void Disable(string reason = "", bool displayConsole = true)
|
||||
{
|
||||
LastThreat = DateTime.UtcNow;
|
||||
SetBuff(33, 330, true); //Weak
|
||||
SetBuff(32, 330, true); //Slow
|
||||
SetBuff(23, 330, true); //Cursed
|
||||
if (!string.IsNullOrEmpty(reason))
|
||||
Log.ConsoleInfo(string.Format("Player {0} has been disabled for {1}.", Name, reason));
|
||||
SetBuff(47, 330, true); //Frozen
|
||||
|
||||
if (ActiveChest != -1)
|
||||
{
|
||||
SendData(PacketTypes.ChestOpen, "", -1);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(reason))
|
||||
{
|
||||
if ((DateTime.UtcNow - LastDisableNotification).TotalMilliseconds > 5000)
|
||||
{
|
||||
if (displayConsole)
|
||||
{
|
||||
Log.ConsoleInfo(string.Format("Player {0} has been disabled for {1}.", Name, reason));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Info("Player {0} has been disabled for {1}.", Name, reason);
|
||||
}
|
||||
LastDisableNotification = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
var trace = new StackTrace();
|
||||
StackFrame frame = null;
|
||||
frame = trace.GetFrame(1);
|
||||
|
|
@ -744,6 +892,177 @@ namespace TShockAPI
|
|||
return TShock.SendBytes(Netplay.serverSock[Index], data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends Raptor permissions to the player.
|
||||
/// </summary>
|
||||
public void SendRaptorPermissions()
|
||||
{
|
||||
if (!IsRaptor)
|
||||
return;
|
||||
|
||||
lock (NetMessage.buffer[Index].writeBuffer)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true))
|
||||
{
|
||||
using (var writer = new BinaryWriter(ms))
|
||||
{
|
||||
writer.BaseStream.Position = 4;
|
||||
|
||||
writer.Write((byte)PacketTypes.Placeholder);
|
||||
writer.Write((byte)RaptorPacketTypes.Permissions);
|
||||
|
||||
writer.Write(String.Join(",", Group.TotalPermissions.ToArray()));
|
||||
|
||||
length = (int)writer.BaseStream.Position;
|
||||
writer.BaseStream.Position = 0;
|
||||
writer.Write(length - 4);
|
||||
}
|
||||
}
|
||||
|
||||
TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sends a region to the player.
|
||||
/// <param name="region">The region.</param>
|
||||
/// </summary>
|
||||
public void SendRaptorRegion(Region region)
|
||||
{
|
||||
if (!IsRaptor)
|
||||
return;
|
||||
|
||||
lock (NetMessage.buffer[Index].writeBuffer)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true))
|
||||
{
|
||||
using (var writer = new BinaryWriter(ms))
|
||||
{
|
||||
writer.BaseStream.Position = 4;
|
||||
|
||||
writer.Write((byte)PacketTypes.Placeholder);
|
||||
writer.Write((byte)RaptorPacketTypes.Region);
|
||||
|
||||
writer.Write(region.Area.X);
|
||||
writer.Write(region.Area.Y);
|
||||
writer.Write(region.Area.Width);
|
||||
writer.Write(region.Area.Height);
|
||||
writer.Write(region.Name);
|
||||
|
||||
length = (int)writer.BaseStream.Position;
|
||||
writer.BaseStream.Position = 0;
|
||||
writer.Write(length - 4);
|
||||
}
|
||||
}
|
||||
|
||||
TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sends a region deletion to the player.
|
||||
/// <param name="regionName">The region name.</param>
|
||||
/// </summary>
|
||||
public void SendRaptorRegionDeletion(string regionName)
|
||||
{
|
||||
if (!IsRaptor)
|
||||
return;
|
||||
|
||||
lock (NetMessage.buffer[Index].writeBuffer)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true))
|
||||
{
|
||||
using (var writer = new BinaryWriter(ms))
|
||||
{
|
||||
writer.BaseStream.Position = 4;
|
||||
|
||||
writer.Write((byte)PacketTypes.Placeholder);
|
||||
writer.Write((byte)RaptorPacketTypes.RegionDelete);
|
||||
|
||||
writer.Write(regionName);
|
||||
|
||||
length = (int)writer.BaseStream.Position;
|
||||
writer.BaseStream.Position = 0;
|
||||
writer.Write(length - 4);
|
||||
}
|
||||
}
|
||||
|
||||
TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sends a warp to the player.
|
||||
/// <param name="warp">The warp.</param>
|
||||
/// </summary>
|
||||
public void SendRaptorWarp(Warp warp)
|
||||
{
|
||||
if (!IsRaptor)
|
||||
return;
|
||||
|
||||
lock (NetMessage.buffer[Index].writeBuffer)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true))
|
||||
{
|
||||
using (var writer = new BinaryWriter(ms))
|
||||
{
|
||||
writer.BaseStream.Position = 4;
|
||||
|
||||
writer.Write((byte)PacketTypes.Placeholder);
|
||||
writer.Write((byte)RaptorPacketTypes.Warp);
|
||||
|
||||
writer.Write(warp.Position.X);
|
||||
writer.Write(warp.Position.Y);
|
||||
writer.Write(warp.Name);
|
||||
|
||||
length = (int)writer.BaseStream.Position;
|
||||
writer.BaseStream.Position = 0;
|
||||
writer.Write(length - 4);
|
||||
}
|
||||
}
|
||||
|
||||
TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sends a warp deletion to the player.
|
||||
/// <param name="warpName">The warp name.</param>
|
||||
/// </summary>
|
||||
public void SendRaptorWarpDeletion(string warpName)
|
||||
{
|
||||
if (!IsRaptor)
|
||||
return;
|
||||
|
||||
lock (NetMessage.buffer[Index].writeBuffer)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
using (var ms = new MemoryStream(NetMessage.buffer[Index].writeBuffer, true))
|
||||
{
|
||||
using (var writer = new BinaryWriter(ms))
|
||||
{
|
||||
writer.BaseStream.Position = 4;
|
||||
|
||||
writer.Write((byte)PacketTypes.Placeholder);
|
||||
writer.Write((byte)RaptorPacketTypes.WarpDelete);
|
||||
|
||||
writer.Write(warpName);
|
||||
|
||||
length = (int)writer.BaseStream.Position;
|
||||
writer.BaseStream.Position = 0;
|
||||
writer.Write(length - 4);
|
||||
}
|
||||
}
|
||||
|
||||
TShock.PacketBuffer.SendBytes(Netplay.serverSock[Index], NetMessage.buffer[Index].writeBuffer, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command callback to a specified command string.
|
||||
/// </summary>
|
||||
|
|
@ -877,6 +1196,24 @@ namespace TShockAPI
|
|||
SetTime(false, 0);
|
||||
}
|
||||
|
||||
public void SetSnowMoon(bool snowMoon)
|
||||
{
|
||||
Main.snowMoon = snowMoon;
|
||||
SetTime(false, 0);
|
||||
}
|
||||
|
||||
public void SetPumpkinMoon(bool pumpkinMoon)
|
||||
{
|
||||
Main.pumpkinMoon = pumpkinMoon;
|
||||
SetTime(false, 0);
|
||||
}
|
||||
|
||||
public void SetEclipse(bool Eclipse)
|
||||
{
|
||||
Main.eclipse = Eclipse;
|
||||
SetTime(true, 150);
|
||||
}
|
||||
|
||||
public void SetTime(bool dayTime, double time)
|
||||
{
|
||||
Main.dayTime = dayTime;
|
||||
|
|
@ -910,12 +1247,12 @@ namespace TShockAPI
|
|||
NetMessage.SendData((int) PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
|
||||
}
|
||||
|
||||
public void RevertTiles(Dictionary<Vector2, TileData> tiles)
|
||||
public void RevertTiles(Dictionary<Vector2, Tile> tiles)
|
||||
{
|
||||
// Update Main.Tile first so that when tile sqaure is sent it is correct
|
||||
foreach (KeyValuePair<Vector2, TileData> entry in tiles)
|
||||
foreach (KeyValuePair<Vector2, Tile> entry in tiles)
|
||||
{
|
||||
Main.tile[(int) entry.Key.X, (int) entry.Key.Y].Data = entry.Value;
|
||||
Main.tile[(int) entry.Key.X, (int) entry.Key.Y] = entry.Value;
|
||||
}
|
||||
// Send all players updated tile sqaures
|
||||
foreach (Vector2 coords in tiles.Keys)
|
||||
|
|
@ -928,9 +1265,14 @@ namespace TShockAPI
|
|||
public class PlayerData
|
||||
{
|
||||
public NetItem[] inventory = new NetItem[NetItem.maxNetInventory];
|
||||
public int health = 100;
|
||||
public int maxHealth = 100;
|
||||
//public int maxMana = 100;
|
||||
public int mana = 20;
|
||||
public int maxMana = 20;
|
||||
public bool exists;
|
||||
public int spawnX= -1;
|
||||
public int spawnY= -1;
|
||||
|
||||
|
||||
public PlayerData(TSPlayer player)
|
||||
{
|
||||
|
|
@ -950,6 +1292,7 @@ namespace TShockAPI
|
|||
this.inventory[2].stack = 1;
|
||||
if (player.TPlayer.inventory[2] != null && player.TPlayer.inventory[2].netID == -16)
|
||||
this.inventory[2].prefix = player.TPlayer.inventory[2].prefix;
|
||||
|
||||
}
|
||||
|
||||
public void StoreSlot(int slot, int netID, int prefix, int stack)
|
||||
|
|
@ -972,14 +1315,28 @@ namespace TShockAPI
|
|||
}
|
||||
}
|
||||
|
||||
public void CopyInventory(TSPlayer player)
|
||||
public void CopyCharacter(TSPlayer player)
|
||||
{
|
||||
this.health = player.TPlayer.statLife > 0 ? player.TPlayer.statLife : 1;
|
||||
this.maxHealth = player.TPlayer.statLifeMax;
|
||||
this.mana = player.TPlayer.statMana;
|
||||
this.maxMana = player.TPlayer.statManaMax;
|
||||
if (player.sX > 0 && player.sY > 0)
|
||||
{
|
||||
this.spawnX = player.sX;
|
||||
this.spawnY = player.sY;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.spawnX = player.TPlayer.SpawnX;
|
||||
this.spawnY = player.TPlayer.SpawnY;
|
||||
}
|
||||
Item[] inventory = player.TPlayer.inventory;
|
||||
Item[] armor = player.TPlayer.armor;
|
||||
Item[] dye = player.TPlayer.dye;
|
||||
for (int i = 0; i < NetItem.maxNetInventory; i++)
|
||||
{
|
||||
if (i < 49)
|
||||
if (i < NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))
|
||||
{
|
||||
if (player.TPlayer.inventory[i] != null)
|
||||
{
|
||||
|
|
@ -1001,11 +1358,12 @@ namespace TShockAPI
|
|||
this.inventory[i].prefix = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (i < NetItem.maxNetInventory - NetItem.dyeSlots)
|
||||
{
|
||||
if (player.TPlayer.armor[i - 48] != null)
|
||||
var index = i - (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots));
|
||||
if (player.TPlayer.armor[index] != null)
|
||||
{
|
||||
this.inventory[i].netID = armor[i - 48].netID;
|
||||
this.inventory[i].netID = armor[index].netID;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1014,8 +1372,31 @@ namespace TShockAPI
|
|||
|
||||
if (this.inventory[i].netID != 0)
|
||||
{
|
||||
this.inventory[i].stack = armor[i - 48].stack;
|
||||
this.inventory[i].prefix = armor[i - 48].prefix;
|
||||
this.inventory[i].stack = armor[index].stack;
|
||||
this.inventory[i].prefix = armor[index].prefix;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.inventory[i].stack = 0;
|
||||
this.inventory[i].prefix = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = i - (NetItem.maxNetInventory - NetItem.dyeSlots);
|
||||
if (player.TPlayer.dye[index] != null)
|
||||
{
|
||||
this.inventory[i].netID = dye[index].netID;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.inventory[i].netID = 0;
|
||||
}
|
||||
|
||||
if (this.inventory[i].netID != 0)
|
||||
{
|
||||
this.inventory[i].stack = dye[index].stack;
|
||||
this.inventory[i].prefix = dye[index].prefix;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1025,15 +1406,137 @@ namespace TShockAPI
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RestoreCharacter(TSPlayer player)
|
||||
{
|
||||
player.TPlayer.statLife = this.health;
|
||||
player.TPlayer.statLifeMax = this.maxHealth;
|
||||
player.TPlayer.statMana = this.maxMana;
|
||||
player.TPlayer.statManaMax = this.maxMana;
|
||||
player.TPlayer.SpawnX = this.spawnX;
|
||||
player.TPlayer.SpawnY = this.spawnY;
|
||||
player.sX = this.spawnX;
|
||||
player.sY = this.spawnY;
|
||||
|
||||
for (int i = 0; i < NetItem.maxNetInventory; i++)
|
||||
{
|
||||
if (i < NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots))
|
||||
{
|
||||
if (this.inventory[i] != null)
|
||||
{
|
||||
player.TPlayer.inventory[i].netDefaults(this.inventory[i].netID);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.TPlayer.inventory[i].netDefaults(0);
|
||||
}
|
||||
|
||||
if (player.TPlayer.inventory[i].netID != 0)
|
||||
{
|
||||
player.TPlayer.inventory[i].stack = this.inventory[i].stack;
|
||||
player.TPlayer.inventory[i].prefix = (byte)this.inventory[i].prefix;
|
||||
}
|
||||
}
|
||||
else if (i < NetItem.maxNetInventory - NetItem.dyeSlots)
|
||||
{
|
||||
var index = i - (NetItem.maxNetInventory - (NetItem.armorSlots + NetItem.dyeSlots));
|
||||
if (this.inventory[i] != null)
|
||||
{
|
||||
player.TPlayer.armor[index].netDefaults(this.inventory[i].netID);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.TPlayer.armor[index].netDefaults(0);
|
||||
}
|
||||
|
||||
if (player.TPlayer.armor[index].netID != 0)
|
||||
{
|
||||
player.TPlayer.armor[index].stack = this.inventory[i].stack;
|
||||
player.TPlayer.armor[index].prefix = (byte)this.inventory[i].prefix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = i - (NetItem.maxNetInventory - NetItem.dyeSlots);
|
||||
if (this.inventory[i] != null)
|
||||
{
|
||||
player.TPlayer.dye[index].netDefaults(this.inventory[i].netID);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.TPlayer.dye[index].netDefaults(0);
|
||||
}
|
||||
|
||||
if (player.TPlayer.dye[index].netID != 0)
|
||||
{
|
||||
player.TPlayer.dye[index].stack = this.inventory[i].stack;
|
||||
player.TPlayer.dye[index].prefix = (byte)this.inventory[i].prefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < 59; k++)
|
||||
{
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].inventory[k].name, player.Index, (float)k, (float)Main.player[player.Index].inventory[k].prefix, 0f, 0);
|
||||
}
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[0].name, player.Index, 59f, (float)Main.player[player.Index].armor[0].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[1].name, player.Index, 60f, (float)Main.player[player.Index].armor[1].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[2].name, player.Index, 61f, (float)Main.player[player.Index].armor[2].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[3].name, player.Index, 62f, (float)Main.player[player.Index].armor[3].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[4].name, player.Index, 63f, (float)Main.player[player.Index].armor[4].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[5].name, player.Index, 64f, (float)Main.player[player.Index].armor[5].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[6].name, player.Index, 65f, (float)Main.player[player.Index].armor[6].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[7].name, player.Index, 66f, (float)Main.player[player.Index].armor[7].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[8].name, player.Index, 67f, (float)Main.player[player.Index].armor[8].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[9].name, player.Index, 68f, (float)Main.player[player.Index].armor[9].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[10].name, player.Index, 69f, (float)Main.player[player.Index].armor[10].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[0].name, player.Index, 70f, (float)Main.player[player.Index].dye[0].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[1].name, player.Index, 71f, (float)Main.player[player.Index].dye[1].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[2].name, player.Index, 72f, (float)Main.player[player.Index].dye[2].prefix, 0f, 0);
|
||||
NetMessage.SendData(4, -1, -1, player.Name, player.Index, 0f, 0f, 0f, 0);
|
||||
NetMessage.SendData(42, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
|
||||
NetMessage.SendData(16, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
|
||||
|
||||
for (int k = 0; k < 59; k++)
|
||||
{
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].inventory[k].name, player.Index, (float)k, (float)Main.player[player.Index].inventory[k].prefix, 0f, 0);
|
||||
}
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[0].name, player.Index, 59f, (float)Main.player[player.Index].armor[0].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[1].name, player.Index, 60f, (float)Main.player[player.Index].armor[1].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[2].name, player.Index, 61f, (float)Main.player[player.Index].armor[2].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[3].name, player.Index, 62f, (float)Main.player[player.Index].armor[3].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[4].name, player.Index, 63f, (float)Main.player[player.Index].armor[4].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[5].name, player.Index, 64f, (float)Main.player[player.Index].armor[5].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[6].name, player.Index, 65f, (float)Main.player[player.Index].armor[6].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[7].name, player.Index, 66f, (float)Main.player[player.Index].armor[7].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[8].name, player.Index, 67f, (float)Main.player[player.Index].armor[8].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[9].name, player.Index, 68f, (float)Main.player[player.Index].armor[9].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[10].name, player.Index, 69f, (float)Main.player[player.Index].armor[10].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[0].name, player.Index, 70f, (float)Main.player[player.Index].dye[0].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[1].name, player.Index, 71f, (float)Main.player[player.Index].dye[1].prefix, 0f, 0);
|
||||
NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[2].name, player.Index, 72f, (float)Main.player[player.Index].dye[2].prefix, 0f, 0);
|
||||
NetMessage.SendData(4, player.Index, -1, player.Name, player.Index, 0f, 0f, 0f, 0);
|
||||
NetMessage.SendData(42, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
|
||||
NetMessage.SendData(16, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
|
||||
|
||||
for (int k = 0; k < 10; k++)
|
||||
{
|
||||
player.TPlayer.buffType[k] = 0;
|
||||
}
|
||||
NetMessage.SendData(50, -1, -1, "", player.Index, 0f, 0f, 0f, 0);
|
||||
NetMessage.SendData(50, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public class NetItem
|
||||
{
|
||||
public static int maxNetInventory = 59;
|
||||
public static readonly int maxNetInventory = 73;
|
||||
public static readonly int armorSlots = 11;
|
||||
public static readonly int dyeSlots = 3;
|
||||
public int netID;
|
||||
public int stack;
|
||||
public int prefix;
|
||||
|
||||
|
||||
public static string ToString(NetItem[] inventory)
|
||||
{
|
||||
string inventoryString = "";
|
||||
|
|
|
|||
1043
TShockAPI/TShock.cs
Normal file → Executable file
1043
TShockAPI/TShock.cs
Normal file → Executable file
File diff suppressed because it is too large
Load diff
|
|
@ -38,6 +38,7 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DocumentationFile>bin\Debug\TShockAPI.XML</DocumentationFile>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
|
|
@ -48,6 +49,7 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DocumentationFile>bin\Release\TShockAPI.XML</DocumentationFile>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="HttpServer">
|
||||
|
|
@ -66,11 +68,7 @@
|
|||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="TerrariaServer, Version=0.0.0.0, Culture=neutral, processorArchitecture=x86">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<ExecutableExtension>.exe</ExecutableExtension>
|
||||
<HintPath>..\TerrariaServerBins\TerrariaServer.exe</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BackupManager.cs" />
|
||||
|
|
@ -78,13 +76,11 @@
|
|||
<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="RaptorPacketTypes.cs" />
|
||||
<Compile Include="Rest\RestPermissions.cs" />
|
||||
<Compile Include="SaveManager.cs" />
|
||||
<Compile Include="DB\BanManager.cs" />
|
||||
<Compile Include="DB\InventoryManager.cs" />
|
||||
<Compile Include="DB\CharacterManager.cs" />
|
||||
<Compile Include="DB\IQueryBuilder.cs" />
|
||||
<Compile Include="DB\ItemManager.cs" />
|
||||
<Compile Include="DB\SqlColumn.cs" />
|
||||
|
|
@ -126,6 +122,7 @@
|
|||
<Compile Include="Rest\RestObject.cs" />
|
||||
<Compile Include="Rest\RestVerbs.cs" />
|
||||
<Compile Include="Rest\SecureRest.cs" />
|
||||
<Compile Include="StatTracker.cs" />
|
||||
<Compile Include="Utils.cs" />
|
||||
<Compile Include="TShock.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
@ -134,12 +131,8 @@
|
|||
<Compile Include="DB\WarpsManager.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="config\groups.txt" />
|
||||
<None Include="TShockAPI.licenseheader" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="config\users.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
|
|
@ -170,9 +163,11 @@
|
|||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="config\itembans.txt" />
|
||||
<ProjectReference Include="..\TerrariaServerAPI\TerrariaAPI-Server.csproj">
|
||||
<Project>{549A7941-D9C9-4544-BAC8-D9EEEAB4D777}</Project>
|
||||
<Name>TerrariaAPI-Server</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ using System.Net;
|
|||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Terraria;
|
||||
using TShockAPI.DB;
|
||||
|
||||
|
|
@ -258,7 +259,7 @@ namespace TShockAPI
|
|||
return found;
|
||||
|
||||
byte plrID;
|
||||
if (byte.TryParse(plr, out plrID))
|
||||
if (byte.TryParse(plr, out plrID) && plrID < Main.maxPlayers)
|
||||
{
|
||||
TSPlayer player = TShock.Players[plrID];
|
||||
if (player != null && player.Active)
|
||||
|
|
@ -307,11 +308,11 @@ namespace TShockAPI
|
|||
tileX = startTileX + Random.Next(tileXRange*-1, tileXRange);
|
||||
tileY = startTileY + Random.Next(tileYRange*-1, tileYRange);
|
||||
j++;
|
||||
} while (TilePlacementValid(tileX, tileY) && !TileClear(tileX, tileY));
|
||||
} while (TilePlacementValid(tileX, tileY) && TileSolid(tileX, tileY));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a tile is valid
|
||||
/// Determines if a tile is valid.
|
||||
/// </summary>
|
||||
/// <param name="tileX">Location X</param>
|
||||
/// <param name="tileY">Location Y</param>
|
||||
|
|
@ -322,14 +323,16 @@ namespace TShockAPI
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the tile is clear.
|
||||
/// Checks if the tile is solid.
|
||||
/// </summary>
|
||||
/// <param name="tileX">Location X</param>
|
||||
/// <param name="tileY">Location Y</param>
|
||||
/// <returns>The state of the tile</returns>
|
||||
private bool TileClear(int tileX, int tileY)
|
||||
/// <returns>The tile's solidity.</returns>
|
||||
public bool TileSolid(int tileX, int tileY)
|
||||
{
|
||||
return !Main.tile[tileX, tileY].active;
|
||||
return TilePlacementValid(tileX, tileY) && Main.tile[tileX, tileY] != null &&
|
||||
Main.tile[tileX, tileY].active() && Main.tileSolid[Main.tile[tileX, tileY].type] &&
|
||||
!Main.tile[tileX, tileY].inActive() && !Main.tile[tileX, tileY].halfBrick() && Main.tile[tileX, tileY].slope() == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -371,7 +374,7 @@ namespace TShockAPI
|
|||
var found = new List<Item>();
|
||||
Item item = new Item();
|
||||
string nameLower = name.ToLower();
|
||||
for (int i = -24; i < Main.maxItemTypes; i++)
|
||||
for (int i = -48; i < Main.maxItemTypes; i++)
|
||||
{
|
||||
item.netDefaults(i);
|
||||
if (item.name.ToLower() == nameLower)
|
||||
|
|
@ -571,10 +574,10 @@ namespace TShockAPI
|
|||
/// <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)
|
||||
if (TShock.Config.ServerSideCharacter)
|
||||
foreach (TSPlayer player in TShock.Players)
|
||||
if (player != null && player.IsLoggedIn && !player.IgnoreActionsForClearingTrashCan)
|
||||
TShock.InventoryDB.InsertPlayerData(player);
|
||||
TShock.CharacterDB.InsertPlayerData(player);
|
||||
|
||||
StopServer(true, reason);
|
||||
System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
|
||||
|
|
@ -589,7 +592,8 @@ namespace TShockAPI
|
|||
FileTools.SetupConfig();
|
||||
TShock.HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs());
|
||||
TShock.Groups.LoadPermisions();
|
||||
TShock.Regions.ReloadAllRegions();
|
||||
TShock.Regions.Reload();
|
||||
TShock.Itembans.UpdateItemBans();
|
||||
Hooks.GeneralHooks.OnReloadEvent(player);
|
||||
}
|
||||
|
||||
|
|
@ -636,16 +640,16 @@ namespace TShockAPI
|
|||
string playerName = player.Name;
|
||||
player.SilentKickInProgress = silent;
|
||||
if (player.IsLoggedIn && saveSSI)
|
||||
player.SaveServerInventory();
|
||||
player.SaveServerCharacter();
|
||||
player.Disconnect(string.Format("Kicked: {0}", reason));
|
||||
Log.ConsoleInfo(string.Format("Kicked {0} for : {1}", playerName, reason));
|
||||
Log.ConsoleInfo(string.Format("Kicked {0} for : '{1}'", playerName, reason));
|
||||
string verb = force ? "force " : "";
|
||||
if (!silent)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(adminUserName))
|
||||
Broadcast(string.Format("{0} was {1}kicked for {2}", playerName, verb, reason.ToLower()), Color.Green);
|
||||
Broadcast(string.Format("{0} was {1}kicked for '{2}'", playerName, verb, reason.ToLower()), Color.Green);
|
||||
else
|
||||
Broadcast(string.Format("{0} {1}kicked {2} for {3}", adminUserName, verb, playerName, reason.ToLower()), Color.Green);
|
||||
Broadcast(string.Format("{0} {1}kicked {2} for '{3}'", adminUserName, verb, playerName, reason.ToLower()), Color.Green);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -673,15 +677,16 @@ namespace TShockAPI
|
|||
if (force || !player.Group.HasPermission(Permissions.immunetoban))
|
||||
{
|
||||
string ip = player.IP;
|
||||
string uuid = player.UUID;
|
||||
string playerName = player.Name;
|
||||
TShock.Bans.AddBan(ip, playerName, reason, false, adminUserName);
|
||||
TShock.Bans.AddBan(ip, playerName, uuid, reason, false, adminUserName);
|
||||
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 " : "";
|
||||
if (string.IsNullOrWhiteSpace(adminUserName))
|
||||
Broadcast(string.Format("{0} was {1}banned for {2}", playerName, verb, reason.ToLower()));
|
||||
Broadcast(string.Format("{0} was {1}banned for '{2}'", playerName, verb, reason.ToLower()));
|
||||
else
|
||||
Broadcast(string.Format("{0} {1}banned {2} for {3}", adminUserName, verb, playerName, reason.ToLower()));
|
||||
Broadcast(string.Format("{0} {1}banned {2} for '{3}'", adminUserName, verb, playerName, reason.ToLower()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -693,7 +698,7 @@ namespace TShockAPI
|
|||
bool expirationExists = DateTime.TryParse(ban.Expiration, out exp);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ban.Expiration) && (expirationExists) &&
|
||||
(DateTime.Now >= exp))
|
||||
(DateTime.UtcNow >= exp))
|
||||
{
|
||||
if (byName)
|
||||
{
|
||||
|
|
@ -713,7 +718,7 @@ namespace TShockAPI
|
|||
/// <summary>
|
||||
/// Shows a file to the user.
|
||||
/// </summary>
|
||||
/// <param name="ply">int player</param>
|
||||
/// <param name="ply">TSPlayer player</param>
|
||||
/// <param name="file">string filename reletave to savedir</param>
|
||||
public void ShowFileToUser(TSPlayer player, string file)
|
||||
{
|
||||
|
|
@ -722,31 +727,28 @@ namespace TShockAPI
|
|||
{
|
||||
while ((foo = tr.ReadLine()) != null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(foo))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foo = foo.Replace("%map%", Main.worldName);
|
||||
foo = foo.Replace("%players%", GetPlayers());
|
||||
//foo = SanitizeString(foo);
|
||||
if (foo.Substring(0, 1) == "%" && foo.Substring(12, 1) == "%") //Look for a beginning color code.
|
||||
Regex reg = new Regex("%\\s*(?<r>\\d{1,3})\\s*,\\s*(?<g>\\d{1,3})\\s*,\\s*(?<b>\\d{1,3})\\s*%");
|
||||
var matches = reg.Matches(foo);
|
||||
Color c = Color.White;
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
string possibleColor = foo.Substring(0, 13);
|
||||
foo = foo.Remove(0, 13);
|
||||
float[] pC = {0, 0, 0};
|
||||
possibleColor = possibleColor.Replace("%", "");
|
||||
string[] pCc = possibleColor.Split(',');
|
||||
if (pCc.Length == 3)
|
||||
byte r, g, b;
|
||||
if (byte.TryParse(match.Groups["r"].Value, out r) &&
|
||||
byte.TryParse(match.Groups["g"].Value, out g) &&
|
||||
byte.TryParse(match.Groups["b"].Value, out b))
|
||||
{
|
||||
try
|
||||
{
|
||||
player.SendMessage(foo, (byte) Convert.ToInt32(pCc[0]), (byte) Convert.ToInt32(pCc[1]),
|
||||
(byte) Convert.ToInt32(pCc[2]));
|
||||
continue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.ToString());
|
||||
}
|
||||
c = new Color(r, g, b);
|
||||
}
|
||||
foo = foo.Remove(match.Index, match.Length);
|
||||
}
|
||||
player.SendMessage(foo);
|
||||
player.SendMessage(foo, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -787,6 +789,18 @@ namespace TShockAPI
|
|||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the player an error message stating that more than one match was found
|
||||
/// appending a csv list of the matches.
|
||||
/// </summary>
|
||||
/// <param name="ply">Player to send the message to</param>
|
||||
/// <param name="matches">An enumerable list with the matches</param>
|
||||
public void SendMultipleMatchError(TSPlayer ply, IEnumerable<object> matches)
|
||||
{
|
||||
ply.SendErrorMessage("More than one match found: {0}", string.Join(",", matches));
|
||||
ply.SendErrorMessage("Use \"my query\" for items with spaces");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default hashing algorithm.
|
||||
/// </summary>
|
||||
|
|
@ -866,6 +880,50 @@ namespace TShockAPI
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to parse a string as a timespan (_d_m_h_s).
|
||||
/// </summary>
|
||||
/// <param name="time">The time string.</param>
|
||||
/// <param name="seconds">The seconds.</param>
|
||||
/// <returns>Whether the string was parsed successfully.</returns>
|
||||
public bool TryParseTime(string str, out int seconds)
|
||||
{
|
||||
seconds = 0;
|
||||
|
||||
var sb = new StringBuilder(3);
|
||||
for (int i = 0; i < str.Length; i++)
|
||||
{
|
||||
if (char.IsDigit(str[i]) || (str[i] == '-' || str[i] == '+'))
|
||||
sb.Append(str[i]);
|
||||
else
|
||||
{
|
||||
int num;
|
||||
if (!int.TryParse(sb.ToString(), out num))
|
||||
return false;
|
||||
|
||||
sb.Clear();
|
||||
switch (str[i])
|
||||
{
|
||||
case 's':
|
||||
seconds += num;
|
||||
break;
|
||||
case 'm':
|
||||
seconds += num * 60;
|
||||
break;
|
||||
case 'h':
|
||||
seconds += num * 60 * 60;
|
||||
break;
|
||||
case 'd':
|
||||
seconds += num * 60 * 60 * 24;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a projectile by identity and owner
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
#Format
|
||||
#name parent permisson1 permission2 permissionN
|
||||
#if there is no parent, put null instead
|
||||
#groups inherit permissions from their parents
|
||||
#put a ! before a permission to negate it
|
||||
#Do not remove the group default
|
||||
#Do not name a group SuperAdmin, that is hard-coded into the code, it grants total permissions
|
||||
#ALWAYS DECLARE A GROUP'S PARENT BEFORE YOU DECLARE THE GROUP
|
||||
|
||||
#currently avaliable permissions:
|
||||
#reservedslot - reserved slot for player
|
||||
#canwater - allow players to use water
|
||||
#canlava - allow players to use lava
|
||||
#canspike - allow players to place spikes
|
||||
#warp - allow players to use warps
|
||||
#kick - kick users
|
||||
#ban - ban players by name or ip
|
||||
#unban - unban players by name or ip
|
||||
#whitelist - add ip to whitelist
|
||||
#maintenance - check for updates/turn off server
|
||||
#causeevents - allow player to drop star/meteor and start invasion/bloodmoon
|
||||
#spawnboss - allow player to spawn bosses
|
||||
#spawnmob - allow player to spawn any npcs
|
||||
#tp - allow player to teleport
|
||||
#tphere - allow a player to teleport players to their position
|
||||
#managewarp - allow player to add/delete warp locations
|
||||
#managegroup - allow player to add/delete/modify groups
|
||||
#manageitem - allow a player to add/delete item bans
|
||||
#manageregion - allow a user to create/edit regions
|
||||
#editspawn - allow player to enable/disable build protection
|
||||
#cfg - allow player to view/change tshock configuration
|
||||
#time - allow player to change time
|
||||
#pvpfun - enable pvpfun commands
|
||||
#logs - notify player when any command is executed
|
||||
#kill - allow player to kill others
|
||||
#butcher - allow player to kill all alive monsters
|
||||
#item - allow player to spawn items
|
||||
#heal - allow player to heal
|
||||
#immunetokick - player can't be kick
|
||||
#immunetoban - player can't be banned
|
||||
#ignorecheatdetection - allow player to cheat (health/mana cheats)
|
||||
#ignoregriefdetection - allow player to grief (use explosives, water, lava even if they dont have premission to)
|
||||
#usebanneditem - allows player to use banned items
|
||||
#manageusers - Grab player info
|
||||
#whisper - allow player to whisper to other players
|
||||
#adminchat - Colors and adds a prefix to the player's chats.
|
||||
#canbuild - allow player to build (does not bypass other checks)
|
||||
|
||||
default null canwater canlava warp canbuild
|
||||
vip default reservedslot
|
||||
newadmin default kick editspawn reservedslot
|
||||
admin newadmin ban unban whitelist causeevents spawnboss spawnmob managewarp time tp pvpfun kill logs immunetokick tphere
|
||||
trustedadmin admin maintenance cfg butcher cheat immunetoban ignorecheatdetection ignoregriefdetection usebanneditem
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#see https://github.com/TShock/TShock/wiki/Item-List for a list of item ids
|
||||
#List each banned item ID below this, with each on a new line
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#format
|
||||
#ip group
|
||||
#see groups.txt for a list of groups
|
||||
#127.0.0.1 superadmin
|
||||
1
TerrariaServerAPI
Submodule
1
TerrariaServerAPI
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 0ddd492aa03e5c97dddbc95b2e605fa2823804ab
|
||||
Binary file not shown.
|
|
@ -54,7 +54,7 @@ namespace UnitTests
|
|||
[TestMethod]
|
||||
public void AddBanTest()
|
||||
{
|
||||
Assert.IsTrue(Bans.AddBan("127.0.0.1", "BanTest", "Ban Testing"));
|
||||
Assert.IsTrue(Bans.AddBan("127.0.0.1", "BanTest", "BanTest2", "Ban Testing"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
@ -62,6 +62,7 @@ namespace UnitTests
|
|||
{
|
||||
Assert.IsNotNull(Bans.GetBanByIp("127.0.0.1"));
|
||||
Assert.IsNotNull(Bans.GetBanByName("BanTest"));
|
||||
Assert.IsNotNull(Bans.GetBanByUUID("BanTest2"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
111
create_release.py
Normal file
111
create_release.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
# Hey there, this is used to compile TShock on the build server.
|
||||
# Don't change it. Thanks!
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import urllib2
|
||||
import zipfile
|
||||
|
||||
cur_wd = os.getcwd()
|
||||
release_dir = os.path.join(cur_wd, "releases")
|
||||
|
||||
terraria_bin_name = "TerrariaServer.exe"
|
||||
sql_bins_names = ["Mono.Data.Sqlite.dll", "MySql.Data.dll", "MySql.Web.dll"]
|
||||
sqlite_dep = "sqlite3.dll"
|
||||
json_bin_name = "Newtonsoft.Json.dll"
|
||||
http_bin_name = "HttpServer.dll"
|
||||
tshock_bin_name = "TShockAPI.dll"
|
||||
tshock_symbols = "TShockAPI.dll.mdb"
|
||||
|
||||
terraria_release_bin = os.path.join(cur_wd, "TerrariaServerAPI", "bin", "Release", terraria_bin_name)
|
||||
terraria_debug_bin = os.path.join(cur_wd, "TerrariaServerAPI", "bin", "Debug", terraria_bin_name)
|
||||
sql_dep = os.path.join(cur_wd, "SqlBins")
|
||||
http_bin = os.path.join(cur_wd, "HttpBins", http_bin_name)
|
||||
json_bin = os.path.join(cur_wd, "TShockAPI", json_bin_name)
|
||||
release_bin = os.path.join(cur_wd, "TShockAPI", "bin", "Release", tshock_bin_name)
|
||||
debug_folder = os.path.join(cur_wd, "TShockAPI", "bin", "Debug")
|
||||
|
||||
|
||||
def create_release_folder():
|
||||
os.mkdir(release_dir)
|
||||
|
||||
def copy_dependencies():
|
||||
shutil.copy(http_bin, release_dir)
|
||||
shutil.copy(json_bin, release_dir)
|
||||
shutil.copy(os.path.join(sql_dep, sqlite_dep), release_dir)
|
||||
for f in sql_bins_names:
|
||||
shutil.copy(os.path.join(sql_dep, f), release_dir)
|
||||
|
||||
def copy_debug_files():
|
||||
shutil.copy(terraria_debug_bin, release_dir)
|
||||
shutil.copy(os.path.join(debug_folder, tshock_bin_name), release_dir)
|
||||
shutil.copy(os.path.join(debug_folder, tshock_symbols), release_dir)
|
||||
|
||||
def copy_release_files():
|
||||
shutil.copy(terraria_release_bin, release_dir)
|
||||
shutil.copy(release_bin, release_dir)
|
||||
shutil.copy(release_bin, release_dir)
|
||||
|
||||
def create_base_zip(name):
|
||||
os.chdir(release_dir)
|
||||
zip = zipfile.ZipFile(name, "w")
|
||||
zip.write(terraria_bin_name)
|
||||
zip.write(sqlite_dep)
|
||||
zip.write(http_bin_name, os.path.join("ServerPlugins", http_bin_name))
|
||||
zip.write(json_bin_name, os.path.join("ServerPlugins", json_bin_name))
|
||||
for f in sql_bins_names:
|
||||
zip.write(f, os.path.join("ServerPlugins", f))
|
||||
return zip
|
||||
|
||||
def package_release():
|
||||
copy_release_files()
|
||||
zip = create_base_zip("tshock_release.zip")
|
||||
zip.write(tshock_bin_name, os.path.join("ServerPlugins", tshock_bin_name))
|
||||
zip.close()
|
||||
os.remove(tshock_bin_name)
|
||||
os.remove(terraria_bin_name)
|
||||
os.chdir(cur_wd)
|
||||
|
||||
def package_debug():
|
||||
copy_debug_files()
|
||||
zip = create_base_zip("tshock_debug.zip")
|
||||
zip.write(tshock_bin_name, os.path.join("ServerPlugins", tshock_bin_name))
|
||||
zip.write(tshock_symbols, os.path.join("ServerPlugins", tshock_symbols))
|
||||
zip.close()
|
||||
os.remove(tshock_bin_name)
|
||||
os.remove(tshock_symbols)
|
||||
os.remove(terraria_bin_name)
|
||||
os.chdir(cur_wd)
|
||||
|
||||
def delete_files():
|
||||
os.chdir(release_dir)
|
||||
for f in sql_bins_names:
|
||||
os.remove(f)
|
||||
os.remove(sqlite_dep)
|
||||
os.remove(json_bin_name)
|
||||
os.remove(http_bin_name)
|
||||
os.chdir(cur_wd)
|
||||
|
||||
def update_terraria_source():
|
||||
subprocess.check_call(['/usr/bin/git', 'submodule', 'init'])
|
||||
subprocess.check_call(['/usr/bin/git', 'submodule', 'update'])
|
||||
|
||||
def build_software():
|
||||
release_proc = subprocess.Popen(['/usr/local/bin/xbuild', './TShockAPI/TShockAPI.csproj', '/p:Configuration=Release'])
|
||||
debug_proc = subprocess.Popen(['/usr/local/bin/xbuild', './TShockAPI/TShockAPI.csproj', '/p:Configuration=Debug'])
|
||||
release_proc.wait()
|
||||
debug_proc.wait()
|
||||
if (release_proc.returncode != 0):
|
||||
raise CalledProcessError(release_proc.returncode)
|
||||
if (debug_proc.returncode != 0):
|
||||
raise CalledProcessError(debug_proc.returncode)
|
||||
|
||||
if __name__ == '__main__':
|
||||
create_release_folder()
|
||||
update_terraria_source()
|
||||
copy_dependencies()
|
||||
build_software()
|
||||
package_release()
|
||||
package_debug()
|
||||
delete_files()
|
||||
|
|
@ -42,6 +42,7 @@ An example configuration file is below.
|
|||
"KickOnMediumcoreDeath": false,
|
||||
"BanOnMediumcoreDeath": false,
|
||||
"AutoSave": true,
|
||||
"AnnounceSave": true,
|
||||
"MaximumLoginAttempts": 3,
|
||||
"RconPassword": "",
|
||||
"RconPort": 7777,
|
||||
|
|
@ -141,6 +142,11 @@ The following is the official documentation for the configuration file:
|
|||
**Description:** Enable/Disable Terrarias built in auto save
|
||||
**Default:** "True"
|
||||
|
||||
## AnnounceSave
|
||||
**Type:** Boolean
|
||||
**Description:** Enable/Disable save announcements
|
||||
**Default:** "True"
|
||||
|
||||
## BackupInterval
|
||||
**Type:** Int32
|
||||
**Description:** Backup frequency in minutes. So, a value of 60 = 60 minutes. Backups are stored in the \tshock\backups folder.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue