diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f7337cb9..be44ed48 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,5 @@ ### Issue Guidelines -Please follow these simple requirements before posting an issue: +Please follow these simple requirements before posting a bug report: - TShock version number - Any stack traces that may have happened when the issue occurred @@ -12,7 +12,7 @@ If something is better suited to be a plugin for TShock, rather than a TShock co ### Pull Request Dev Guidelines -These guidelines are for all contributors. +These guidelines are for all contributors. Please join #pull-request on our Slack instance and ask about your idea first, if you're implementing a new feature, system, or changing an existing implementation. Pull requests that change large feature sets or swathes of code will be dissected for quality and purpose prior to approval, and requests that conflict with a team developer's work may be declined if the project is already being worked on internally, but not released. In addition, issues assigned to Nyx developers that are recent and fresh should be considered a no-go zone, while that developer works on their solution outside the scope of Github. Required: - Push code to the general-devel branch. Do not push it anywhere else. @@ -31,10 +31,14 @@ These guidelines are to be followed by all developers with commit level access t - __Do not force push the repo__, or you will be removed. - __Do not revert commits__, unless you have sign-off from one other developer (the two-man rule), or you will be removed. - __This is not a meritocracy.__ +- Deprecation of a function guarantees that it will exist in the given release, but may be removed, at any time following, from subsequent releases without further warning. Warning should be given in the release thread prior to it going live. +- Updates should be discussed, via pull request of a version tick, prior to release. Only after consensus from active contributing community members has been given can a release happen. +- Breaking API changes (excluding removal of already deprecated and warned code) should be forewarned with a one week notice on the forums, which may be given at any time prior to release (as soon as a pull request for a version push has been made, an update can be warned). +- Major changes to the TShock architecture should be discussed in github issue form with the community. These changes include removal of commands, restructuring, improvements, and new features. For example, adding silent command processing or a new REST api level. Consensus is required from at minimum, a majority of contributors present and reachable in the community (plugin authors or commit players) during the last seven days. #### Pull Request Acceptance Guidelines -- Don't ruin someone's first time sending a pull request. They feel demotivated, and then they won't want to push any more code for us. +- Don't ruin someone's first time sending a pull request. They feel de-motivated, and then they won't want to push any more code for us. - Don't accept untested pull requests from the outside world. Bamboo and Travis will at least make sure that something compiles, but actual code and execution tests are required. - Pull request acceptance from internal contributors (anyone with write access) requires only one other approval to merge. - Pull request acceptance from external contributors (anyone without write access) requires the [two-man rule](https://en.wikipedia.org/wiki/Two-man_rule) to be followed. If another man/woman/child in the two-man rule cannot be found within seven days, then this requirement is exempted. diff --git a/README.md b/README.md index 86aa841b..8241f47b 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ Feeling like helping out? Want to find an awesome server? Some awesome plugins? * [Wiki](https://tshock.atlassian.net/wiki/display/TSHOCKPLUGINS/Home) * [Join our chat (supports IRC, XMPP, iOS, Android, Web)](http://chat.tshock.co/) +If your intention is to send a pull request or code change, please join #pull-request in Slack to discuss your changes with the team. For more contributing guidelines, see the contributing file. + ## Download * [Github Releases](https://github.com/TShock/TShock/releases) diff --git a/TShockAPI/FileTools.cs b/TShockAPI/FileTools.cs index 071da3fc..c820294e 100644 --- a/TShockAPI/FileTools.cs +++ b/TShockAPI/FileTools.cs @@ -17,6 +17,7 @@ along with this program. If not, see . */ using System; +using System.Collections.Generic; using System.IO; using TShockAPI.ServerSideCharacters; @@ -24,33 +25,35 @@ namespace TShockAPI { public class FileTools { - /// - /// Path to the file containing the rules. - /// + private const string MotdFormat = + "This server is running TShock for Terraria.\n Type /help for a list of commands.\n%255,000,000%Current map: %map%\nCurrent players: %players%"; + /// + /// Path to the file containing the rules. + /// internal static string RulesPath { get { return Path.Combine(TShock.SavePath, "rules.txt"); } } - /// - /// Path to the file containing the message of the day. - /// + /// + /// Path to the file containing the message of the day. + /// internal static string MotdPath { get { return Path.Combine(TShock.SavePath, "motd.txt"); } } - /// - /// Path to the file containing the whitelist. - /// + /// + /// Path to the file containing the whitelist. + /// internal static string WhitelistPath { get { return Path.Combine(TShock.SavePath, "whitelist.txt"); } } - /// - /// Path to the file containing the config. - /// + /// + /// Path to the file containing the config. + /// internal static string ConfigPath { get { return Path.Combine(TShock.SavePath, "config.json"); } @@ -64,20 +67,20 @@ namespace TShockAPI get { return Path.Combine(TShock.SavePath, "sscconfig.json"); } } - /// - /// Creates an empty file at the given path. - /// - /// The path to the file. + /// + /// Creates an empty file at the given path. + /// + /// The path to the file. public static void CreateFile(string file) { File.Create(file).Close(); } - /// - /// Creates a file if the files doesn't already exist. - /// - /// The path to the files - /// The data to write to the file. + /// + /// Creates a file if the files doesn't already exist. + /// + /// The path to the files + /// The data to write to the file. public static void CreateIfNot(string file, string data = "") { if (!File.Exists(file)) @@ -97,8 +100,8 @@ namespace TShockAPI } CreateIfNot(RulesPath, "Respect the admins!\nDon't use TNT!"); - CreateIfNot(MotdPath, - "This server is running TShock for Terraria.\n Type /help for a list of commands.\n%255,000,000%Current map: %map%\nCurrent players: %players%"); + CreateIfNot(MotdPath, MotdFormat); + CreateIfNot(WhitelistPath); if (File.Exists(ConfigPath)) { @@ -112,6 +115,19 @@ namespace TShockAPI TShock.ServerSideCharacterConfig = ServerSideConfig.Read(ServerSideCharacterConfigPath); // Add all the missing config properties in the json file } + else + { + TShock.ServerSideCharacterConfig = new ServerSideConfig + { + StartingInventory = + new List() + { + new NetItem() {netID = -15, stack = 1, prefix = 0}, + new NetItem() {netID = -13, stack = 1, prefix = 0}, + new NetItem() {netID = -16, stack = 1, prefix = 0} + } + }; + } TShock.ServerSideCharacterConfig.Write(ServerSideCharacterConfigPath); } diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 2fc5fed6..c746dbd1 100755 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -1284,9 +1284,15 @@ namespace TShockAPI bypassTrashCanCheck = true; } - if (OnPlayerSlot(plr, slot, stack, prefix, type) || plr != args.Player.Index || slot < 0 || slot > NetItem.maxNetInventory || args.Player.IgnoreSSCPackets) + if (OnPlayerSlot(plr, slot, stack, prefix, type) || plr != args.Player.Index || slot < 0 || + slot > NetItem.maxNetInventory) return true; - + if (args.Player.IgnoreSSCPackets) + { + args.Player.SendData(PacketTypes.PlayerSlot, "", args.Player.Index, slot); + return true; + } + // Garabage? Or will it cause some internal initialization or whatever? var item = new Item(); item.netDefaults(type); diff --git a/TShockAPI/ServerSideCharacters/ServerSideConfig.cs b/TShockAPI/ServerSideCharacters/ServerSideConfig.cs index ea4cc931..cb54716d 100644 --- a/TShockAPI/ServerSideCharacters/ServerSideConfig.cs +++ b/TShockAPI/ServerSideCharacters/ServerSideConfig.cs @@ -20,6 +20,8 @@ along with this program. If not, see . */ using System.IO; +using System.Linq; +using System.Text; using Newtonsoft.Json; namespace TShockAPI.ServerSideCharacters @@ -27,7 +29,7 @@ namespace TShockAPI.ServerSideCharacters public class ServerSideConfig { [Description("Enable server side characters, This stops the client from saving character data! EXPERIMENTAL!!!!!")] - public bool Enabled; + public bool Enabled = false; [Description("How often SSC should save, in minutes.")] public int ServerSideCharacterSave = 5; @@ -61,5 +63,37 @@ namespace TShockAPI.ServerSideCharacters writer.Write(JsonConvert.SerializeObject(this, Formatting.Indented)); } } + + /// + /// Dumps all configuration options to a text file in Markdown format + /// + public static void DumpDescriptions() + { + var sb = new StringBuilder(); + var defaults = new ServerSideConfig(); + + foreach (var field in defaults.GetType().GetFields().OrderBy(f => f.Name)) + { + if (field.IsStatic) + continue; + + var name = field.Name; + var type = field.FieldType.Name; + + var descattr = + field.GetCustomAttributes(false).FirstOrDefault(o => o is DescriptionAttribute) as DescriptionAttribute; + var desc = descattr != null && !string.IsNullOrWhiteSpace(descattr.Description) ? descattr.Description : "None"; + + 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(); + } + + File.WriteAllText("ServerSideConfigDescriptions.txt", sb.ToString()); + } } } diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 17fa8667..7f9fbced 100755 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -1140,18 +1140,6 @@ namespace TShockAPI { this.inventory[i] = new NetItem(); } - this.inventory[0].netID = -15; - this.inventory[0].stack = 1; - if (player.TPlayer.inventory[0] != null && player.TPlayer.inventory[0].netID == -15) - this.inventory[0].prefix = player.TPlayer.inventory[0].prefix; - this.inventory[1].netID = -13; - this.inventory[1].stack = 1; - if (player.TPlayer.inventory[1] != null && player.TPlayer.inventory[1].netID == -13) - this.inventory[1].prefix = player.TPlayer.inventory[1].prefix; - this.inventory[2].netID = -16; - 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; for (int i = 0; i < TShock.ServerSideCharacterConfig.StartingInventory.Count; i++) { diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index bef1506a..f7f32205 100755 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -77,6 +77,7 @@ namespace TShockAPI public static StatTracker StatTracker = new StatTracker(); public static UpdateManager UpdateManager; public static ILog Log; + public static TerrariaPlugin instance; /// /// Used for implementing REST Tokens prior to the REST system starting up. /// @@ -116,6 +117,7 @@ namespace TShockAPI ServerSideCharacterConfig.StartingInventory.Add(new NetItem { netID = -13, prefix = 0, stack = 1 }); ServerSideCharacterConfig.StartingInventory.Add(new NetItem { netID = -16, prefix = 0, stack = 1 }); Order = 0; + instance = this; } @@ -261,7 +263,7 @@ namespace TShockAPI ServerApi.Hooks.ProjectileSetDefaults.Register(this, OnProjectileSetDefaults); ServerApi.Hooks.WorldStartHardMode.Register(this, OnStartHardMode); ServerApi.Hooks.WorldSave.Register(this, SaveManager.Instance.OnSaveWorld); - ServerApi.Hooks.WorldChristmasCheck.Register(this, OnXmasCheck); + ServerApi.Hooks.WorldChristmasCheck.Register(this, OnXmasCheck); ServerApi.Hooks.WorldHalloweenCheck.Register(this, OnHalloweenCheck); ServerApi.Hooks.NetNameCollision.Register(this, NetHooks_NameCollision); Hooks.PlayerHooks.PlayerPreLogin += OnPlayerPreLogin; @@ -516,6 +518,8 @@ namespace TShockAPI case "-dump": ConfigFile.DumpDescriptions(); Permissions.DumpDescriptions(); + ServerSideConfig.DumpDescriptions(); + Environment.Exit(1); break; } } diff --git a/TShockAPI/TextLog.cs b/TShockAPI/TextLog.cs index 5edfeb8b..9812e168 100644 --- a/TShockAPI/TextLog.cs +++ b/TShockAPI/TextLog.cs @@ -20,6 +20,7 @@ using System; using System.Diagnostics; using System.Globalization; using System.IO; +using TerrariaApi.Server; namespace TShockAPI { @@ -226,15 +227,17 @@ namespace TShockAPI caller = meth.DeclaringType.Name; } - try - { - _logWriter.WriteLine("{0} - {1}: {2}: {3}", + var logEntry = String.Format("{0} - {1}: {2}: {3}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture), caller, level.ToString().ToUpper(), message); + try + { + _logWriter.WriteLine(logEntry); _logWriter.Flush(); } catch (ObjectDisposedException) { + ServerApi.LogWriter.PluginWriteLine(TShock.instance, logEntry, TraceLevel.Error); Console.WriteLine("Unable to write to log as log has been disposed."); Console.WriteLine("{0} - {1}: {2}: {3}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture), diff --git a/deploy_release.py b/deploy_release.py index 7fbd1461..fc30c373 100644 --- a/deploy_release.py +++ b/deploy_release.py @@ -3,9 +3,49 @@ import json import sys import os import subprocess +import base64 +import urllib create_release_url = 'https://api.github.com/repos/NyxStudios/TShock/releases' +config_doc_get_url = 'https://tshock.atlassian.net/wiki/rest/api/content/%s?expand=body.storage,version,ancestors' +config_doc_put_url = 'https://tshock.atlassian.net/wiki/rest/api/content/%s' +config_desc_page = "3047451" +ssc_desc_page = "39845891" +permissions_desc_page = "3047433" + +def get_confluence_page(id): + confluence_header = {"Content-Type":"application/json"} + r = requests.get(config_doc_get_url % id, auth=(os.environ["bamboo_confluence_username"], os.environ["bamboo_confluence_password"]), headers=confluence_header) + page = json.loads(r.text) + return page + +def put_confluence_page(page): + confluence_header = {"Content-Type":"application/json"} + page['version']['number'] = page['version']['number'] + 1 + r = requests.put(config_doc_put_url % page['id'], auth=(os.environ["bamboo_confluence_username"], os.environ["bamboo_confluence_password"]), headers=confluence_header, data=json.dumps(page)) + page = json.loads(r.text) + return page + +def update_confluence_page(id, content): + page = get_confluence_page(id) + page['body']['storage']['value'] = content + page['body']['storage']['representation'] = 'storage' + put_confluence_page(page) + +def read_and_update_config_on_confluence(id, file): + #Read the Config + config = "" + with open(file, "r") as f: + line = f.readline() + while (line is not ""): + if (config is not ""): + config = config + '
' + config = config + line + line = f.readline() + #update confluence page + update_confluence_page(id, config) + #Load variables from ENV, which are put there by the bamboo build. branch = os.environ["GIT_BRANCH"] tag_name = os.environ["bamboo_tag_name"] @@ -17,7 +57,7 @@ release_name = 'tshock_' + tag_name[1:] + '.zip' #because we can't find any other secure way to get a token into this script run from bamboo :'( with open('/home/bamboo/scripts/token.py') as f: - token = f.read().rsplit('=', 1)[1].strip() + # token = f.read().rsplit('=', 1)[1].strip() #invoke the mv command on the artifact from bamboo to the new name above subprocess.call('mv tshock_release.zip ' + release_name, shell=True) @@ -47,3 +87,7 @@ upload_headers = {'Authorization': 'token ' + token, 'Content-Type':'application #upload the binary, resulting in a complete binary r = requests.post(upload_url, data=open(release_name, 'rb'), headers = upload_headers, verify=False) + +read_and_update_config_on_confluence(config_desc_page, "ConfigDescriptions.txt") +read_and_update_config_on_confluence(ssc_desc_page, "ServerSideConfigDescriptions.txt") +read_and_update_config_on_confluence(permissions_desc_page, "PermissionsDescriptions.txt") \ No newline at end of file diff --git a/test_release.py b/test_release.py new file mode 100644 index 00000000..bcd69c61 --- /dev/null +++ b/test_release.py @@ -0,0 +1,17 @@ +import subprocess +import shutil +import os.path +import zipfile + +def generate_release(): + zip = zipfile.ZipFile("tshock_release.zip", "r") + zip.extractall() + +def generate_configs(): + subprocess.call(['/usr/local/bin/mono', 'TerrariaServer.exe', '-dump']) + if not os.path.isfile('ConfigDescriptions.txt') or not os.path.isfile('PermissionsDescriptions.txt') or not os.path.isfile('ServerSideConfigDescriptions.txt'): + raise CalledProcessError(1) + +if __name__ == '__main__': + generate_release() + generate_configs() \ No newline at end of file