diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 1b663f40b6..50deb39584 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -27,10 +27,13 @@ + + + diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index a27804dbe2..199085fcb3 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -567,6 +567,9 @@ + + + diff --git a/openrct2.vcxproj.user b/openrct2.vcxproj.user index 6e6c19d6fb..ccf34d4657 100644 --- a/openrct2.vcxproj.user +++ b/openrct2.vcxproj.user @@ -7,7 +7,7 @@ $(TargetDir)\openrct2.exe WindowsLocalDebugger $(TargetDir) - --port=233 + host "C:\Users\Ted\Documents\OpenRCT2\save\Forest Frontiers MP.sv6" $(TargetDir) diff --git a/src/cmdline.c b/src/cmdline.c index 6c3e57081e..194a95b475 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -47,12 +47,6 @@ typedef int (*cmdline_action)(const char **argv, int argc); int gExitCode = 0; int sprite_mode; -#ifndef DISABLE_NETWORK -int gNetworkStart = NETWORK_MODE_NONE; -char gNetworkStartHost[128]; -int gNetworkStartPort = NETWORK_DEFAULT_PORT; -#endif // DISABLE_NETWORK - static void print_launch_information(); static void print_version(); static int cmdline_call_action(const char **argv, int argc); diff --git a/src/cmdline.h b/src/cmdline.h index e29bc5ea67..dd11f23549 100644 --- a/src/cmdline.h +++ b/src/cmdline.h @@ -28,10 +28,6 @@ extern int gExitCode; extern int sprite_mode; -extern int gNetworkStart; -extern char gNetworkStartHost[128]; -extern int gNetworkStartPort; - int cmdline_run(const char **argv, int argc); int cmdline_for_sprite(const char **argv, int argc); diff --git a/src/cmdline/CommandLine.cpp b/src/cmdline/CommandLine.cpp index fdac6a6d7a..0a368f20d7 100644 --- a/src/cmdline/CommandLine.cpp +++ b/src/cmdline/CommandLine.cpp @@ -93,6 +93,7 @@ namespace CommandLine constexpr const char * HelpText = "openrct2 -ha shows help for all commands. " "openrct2 -h will show help and details for a given command."; + static void PrintHelpFor(const CommandLineCommand * commands); static void PrintOptions(const CommandLineOptionDefinition *options); static void PrintExamples(const CommandLineExample *examples); static utf8 * GetOptionCaption(utf8 * buffer, size_t bufferSize, const CommandLineOptionDefinition *option); @@ -104,27 +105,61 @@ namespace CommandLine static bool ParseLongOption(const CommandLineOptionDefinition * options, CommandLineArgEnumerator * argEnumerator, const char * argument); static bool ParseOptionValue(const CommandLineOptionDefinition * option, const char * valueString); - void PrintHelp() + void PrintHelp(bool allCommands) + { + PrintHelpFor(RootCommands); + PrintExamples(RootExamples); + + if (allCommands) + { + const CommandLineCommand * command; + for (command = RootCommands; command->Name != nullptr; command++) + { + if (command->SubCommands != nullptr) + { + size_t commandNameLength = String::LengthOf(command->Name); + for (size_t i = 0; i < commandNameLength; i++) + { + Console::Write("-"); + } + Console::WriteLine(); + Console::WriteLine(command->Name); + for (size_t i = 0; i < commandNameLength; i++) + { + Console::Write("-"); + } + Console::WriteLine(); + PrintHelpFor(command->SubCommands); + } + } + } + else + { + Console::WriteLine(HelpText); + } + } + + static void PrintHelpFor(const CommandLineCommand * commands) { const CommandLineCommand * command; - size_t maxNameLength = 0; - size_t maxParamsLength = 0; + + // Print usage + const char * usageString = "usage: openrct2 "; + const size_t usageStringLength = String::LengthOf(usageString); + Console::Write(usageString); // Get the largest command name length and parameter length - for (command = RootCommands; command->Name != nullptr; command++) + size_t maxNameLength = 0; + size_t maxParamsLength = 0; + for (command = commands; command->Name != nullptr; command++) { maxNameLength = Math::Max(maxNameLength, String::LengthOf(command->Name)); maxParamsLength = Math::Max(maxParamsLength, String::LengthOf(command->Parameters)); } - // Print usage / main commands - const char * usageString = "usage: openrct2 "; - const size_t usageStringLength = String::LengthOf(usageString); - - Console::Write(usageString); - for (command = RootCommands; command->Name != nullptr; command++) + for (command = commands; command->Name != nullptr; command++) { - if (command != RootCommands) + if (command != commands) { Console::WriteSpace(usageStringLength); } @@ -150,10 +185,10 @@ namespace CommandLine } Console::WriteLine(); - PrintOptions(RootCommands->Options); - PrintExamples(RootExamples); - - Console::WriteLine(HelpText); + if (commands->Options != nullptr) + { + PrintOptions(commands->Options); + } } static void PrintOptions(const CommandLineOptionDefinition *options) @@ -169,7 +204,7 @@ namespace CommandLine maxOptionLength = Math::Max(maxOptionLength, optionCaptionLength); } - option = RootCommands->Options; + option = options; for (; option->Type != 255; option++) { Console::WriteSpace(4); @@ -239,11 +274,6 @@ namespace CommandLine return buffer; } - void PrintUsageFor(const char * command) - { - - } - const CommandLineCommand * FindCommandFor(const CommandLineCommand * commands, CommandLineArgEnumerator *argEnumerator) { // Check if end of arguments or options have started @@ -288,8 +318,10 @@ namespace CommandLine static bool ParseOptions(const CommandLineOptionDefinition * options, CommandLineArgEnumerator *argEnumerator) { + bool firstOption = true; + const char * argument; - if (argEnumerator->TryPopString(&argument)) + while (argEnumerator->TryPopString(&argument)) { if (argument[0] == '-') { @@ -308,11 +340,16 @@ namespace CommandLine } } } - else + else if (!firstOption) { Console::WriteLineError("All options must be passed at the end of the command line."); return false; } + else + { + break; + } + firstOption = false; } return true; diff --git a/src/cmdline/CommandLine.hpp b/src/cmdline/CommandLine.hpp index 8a1c340c5b..c6f16f082b 100644 --- a/src/cmdline/CommandLine.hpp +++ b/src/cmdline/CommandLine.hpp @@ -83,10 +83,11 @@ constexpr char NAC = '\0'; namespace CommandLine { extern const CommandLineCommand RootCommands[]; + extern const CommandLineCommand ScreenshotCommands[]; + extern const CommandLineCommand SpriteCommands[]; + extern const CommandLineExample RootExamples[]; - void PrintHelp(); - void PrintUsageFor(const char * command); - + void PrintHelp(bool allCommands = false); exitcode_t HandleCommandDefault(); } diff --git a/src/cmdline/RootCommands.cpp b/src/cmdline/RootCommands.cpp index eb6aa3351c..f5d1d2a1e1 100644 --- a/src/cmdline/RootCommands.cpp +++ b/src/cmdline/RootCommands.cpp @@ -1,16 +1,32 @@ +#include + +extern "C" +{ + #include "../openrct2.h" +} + #include "../core/Console.hpp" +#include "../core/Memory.hpp" +#include "../core/String.hpp" +#include "../network/network.h" #include "CommandLine.hpp" -const CommandLineCommand * ScreenshotCommandTable; -const CommandLineCommand * SpriteCommandTable; +#ifndef DISABLE_NETWORK +int gNetworkStart = NETWORK_MODE_NONE; +char gNetworkStartHost[128]; +int gNetworkStartPort = NETWORK_DEFAULT_PORT; +#endif static bool _help = false; static bool _version = false; static bool _noInstall = false; +static bool _all = false; static bool _about = false; static bool _verbose = false; static bool _headless = false; +#ifndef DISABLE_NETWORK static uint32 _port = 0; +#endif static utf8 * _userDataPath = nullptr; static utf8 * _openrctDataPath = nullptr; @@ -19,31 +35,42 @@ static const CommandLineOptionDefinition StandardOptions[] { CMDLINE_TYPE_SWITCH, &_help, 'h', "help", "show this help message and exit" }, { CMDLINE_TYPE_SWITCH, &_version, 'v', "version", "show version information and exit" }, { CMDLINE_TYPE_SWITCH, &_noInstall, 'n', "no-install", "do not install scenario if passed" }, - { CMDLINE_TYPE_SWITCH, &_about, NAC, "about" , "show information about " OPENRCT2_NAME }, + { CMDLINE_TYPE_SWITCH, &_all, 'a', "all", "show help for all commands" }, + { CMDLINE_TYPE_SWITCH, &_about, NAC, "about", "show information about " OPENRCT2_NAME }, { CMDLINE_TYPE_SWITCH, &_verbose, NAC, "verbose", "log verbose messages" }, { CMDLINE_TYPE_SWITCH, &_headless, NAC, "headless", "run " OPENRCT2_NAME " headless" }, +#ifndef DISABLE_NETWORK { CMDLINE_TYPE_INTEGER, &_port, NAC, "port", "port to use for hosting or joining a server" }, +#endif { CMDLINE_TYPE_STRING, &_userDataPath, NAC, "user-data-path", "path to the user data directory (containing config.ini)" }, { CMDLINE_TYPE_STRING, &_openrctDataPath, NAC, "openrct-data-path", "path to the OpenRCT2 data directory (containing languages)" }, OptionTableEnd }; static exitcode_t HandleNoCommand(CommandLineArgEnumerator * enumerator); +static exitcode_t HandleCommandEdit(CommandLineArgEnumerator * enumerator); static exitcode_t HandleCommandIntro(CommandLineArgEnumerator * enumerator); static exitcode_t HandleCommandHost(CommandLineArgEnumerator * enumerator); static exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator); +static void PrintAbout(); +static void PrintVersion(); +static void PrintLaunchInformation(); + const CommandLineCommand CommandLine::RootCommands[] { // Main commands DefineCommand("", "", StandardOptions, HandleNoCommand ), + DefineCommand("edit", "", StandardOptions, HandleCommandEdit ), DefineCommand("intro", "", StandardOptions, HandleCommandIntro), +#ifndef DISABLE_NETWORK DefineCommand("host", "", StandardOptions, HandleCommandHost ), DefineCommand("join", "", StandardOptions, HandleCommandJoin ), +#endif // Sub-commands - DefineSubCommand("screenshot", ScreenshotCommandTable), - DefineSubCommand("sprite", SpriteCommandTable ), + DefineSubCommand("screenshot", CommandLine::ScreenshotCommands), + DefineSubCommand("sprite", CommandLine::SpriteCommands ), CommandTableEnd }; @@ -54,19 +81,57 @@ static const CommandLineExample CommandLine::RootExamples[] { "./SnowyPark.sc6", "install and open a scenario" }, { "./ShuttleLoop.td6", "install a track" }, { "http:/openrct2.website/files/SnowyPark.sv6", "download and open a saved park" }, +#ifndef DISABLE_NETWORK { "host ./my_park.sv6 --port 11753 --headless", "run a headless server for a saved park" }, +#endif ExampleTableEnd }; exitcode_t CommandLine::HandleCommandDefault() { - if (_help) + exitcode_t result = EXITCODE_CONTINUE; + + if (_about) { - CommandLine::PrintHelp(); - return EXITCODE_OK; + PrintAbout(); + result = EXITCODE_OK; + } else + { + if (_verbose) + { + _log_levels[DIAGNOSTIC_LEVEL_VERBOSE] = 1; + PrintLaunchInformation(); + } + + if (_version) + { + if (!_verbose) + { + PrintVersion(); + } + result = EXITCODE_OK; + } } - return EXITCODE_CONTINUE; + if (_help) + { + CommandLine::PrintHelp(_all); + result = EXITCODE_OK; + } + + gOpenRCT2Headless = _headless; + + if (_userDataPath != NULL) { + String::Set(gCustomUserDataPath, sizeof(gCustomUserDataPath), _userDataPath); + Memory::Free(_userDataPath); + } + + if (_openrctDataPath != NULL) { + String::Set(gCustomOpenrctDataPath, sizeof(gCustomOpenrctDataPath), _openrctDataPath); + Memory::Free(gCustomOpenrctDataPath); + } + + return result; } exitcode_t HandleNoCommand(CommandLineArgEnumerator * enumerator) @@ -77,8 +142,35 @@ exitcode_t HandleNoCommand(CommandLineArgEnumerator * enumerator) return result; } - // Process URI + const char * parkUri; + if (!enumerator->TryPopString(&parkUri)) + { + Console::WriteLineError("Expected path or URL to a saved park."); + return EXITCODE_FAIL; + } + String::Set(gOpenRCT2StartupActionPath, sizeof(gOpenRCT2StartupActionPath), parkUri); + gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; + return EXITCODE_CONTINUE; +} + +exitcode_t HandleCommandEdit(CommandLineArgEnumerator * enumerator) +{ + exitcode_t result = CommandLine::HandleCommandDefault(); + if (result != EXITCODE_CONTINUE) + { + return result; + } + + const char * parkUri; + if (!enumerator->TryPopString(&parkUri)) + { + Console::WriteLineError("Expected path or URL to a saved park."); + return EXITCODE_FAIL; + } + String::Set(gOpenRCT2StartupActionPath, sizeof(gOpenRCT2StartupActionPath), parkUri); + + gOpenRCT2StartupAction = STARTUP_ACTION_EDIT; return EXITCODE_CONTINUE; } @@ -90,68 +182,106 @@ exitcode_t HandleCommandIntro(CommandLineArgEnumerator * enumerator) return result; } + gOpenRCT2StartupAction = STARTUP_ACTION_INTRO; return EXITCODE_CONTINUE; } +#ifndef DISABLE_NETWORK + exitcode_t HandleCommandHost(CommandLineArgEnumerator * enumerator) { - const char * parkUri; - exitcode_t result = CommandLine::HandleCommandDefault(); if (result != EXITCODE_CONTINUE) { return result; } + const char * parkUri; if (!enumerator->TryPopString(&parkUri)) { Console::WriteLineError("Expected path or URL to a saved park."); - CommandLine::PrintUsageFor("host"); return EXITCODE_FAIL; } + gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; + String::Set(gOpenRCT2StartupActionPath, sizeof(gOpenRCT2StartupActionPath), parkUri); + + gNetworkStart = NETWORK_MODE_SERVER; + gNetworkStartPort = _port; return EXITCODE_CONTINUE; } exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator) { - const char * hostname; - exitcode_t result = CommandLine::HandleCommandDefault(); if (result != EXITCODE_CONTINUE) { return result; } + const char * hostname; if (!enumerator->TryPopString(&hostname)) { Console::WriteLineError("Expected a hostname or IP address to the server to connect to."); - CommandLine::PrintUsageFor("join"); return EXITCODE_FAIL; } + gNetworkStart = NETWORK_MODE_CLIENT; + gNetworkStartPort = _port; + String::Set(gNetworkStartHost, sizeof(gNetworkStartHost), hostname); return EXITCODE_CONTINUE; } -const CommandLineCommand ScreenshotCommands[] -{ - // Main commands - DefineCommand("", " [ ]", nullptr, nullptr), - DefineCommand("", " giant ", nullptr, nullptr), - CommandTableEnd -}; +#endif // DISABLE_NETWORK -const CommandLineOptionDefinition SpriteOptions[] +static void PrintAbout() { - { CMDLINE_TYPE_STRING, nullptr, 'm', "mode", "the type of sprite conversion " }, - OptionTableEnd -}; + PrintVersion(); + Console::WriteLine(); + Console::WriteLine("OpenRCT2 is an amusement park simulation game based upon the popular game"); + Console::WriteLine("RollerCoaster Tycoon 2, written by Chris Sawyer. It attempts to mimic the "); + Console::WriteLine("original game as closely as possible while extending it with new features."); + Console::WriteLine("OpenRCT2 is licensed under the GNU General Public License version 3.0, but"); + Console::WriteLine("includes some 3rd party software under different licenses. See the file"); + Console::WriteLine("\"licence.txt\" shipped with the game for details."); + Console::WriteLine(); + Console::WriteLine("Website: https://openrct2.website"); + Console::WriteLine("GitHub: https://github.com/OpenRCT2/OpenRCT2"); + Console::WriteLine("Contributors: https://github.com/OpenRCT2/OpenRCT2/blob/develop/contributors.md"); + Console::WriteLine(); +} -const CommandLineCommand SpriteCommands[] +static void PrintVersion() { - // Main commands - DefineCommand("details", " [idx]", SpriteOptions, nullptr), - DefineCommand("export", " ", SpriteOptions, nullptr), - DefineCommand("build", " [silent]", SpriteOptions, nullptr), - CommandTableEnd -}; + char buffer[256]; + openrct2_write_full_version_info(buffer, sizeof(buffer)); + Console::WriteLine(buffer); + Console::WriteFormat("%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); + Console::WriteLine(); +} + +static void PrintLaunchInformation() +{ + char buffer[256]; + time_t timer; + struct tm * tmInfo; + + // Print name and version information + openrct2_write_full_version_info(buffer, sizeof(buffer)); + Console::WriteFormat("%s", buffer); + Console::WriteLine(); + Console::WriteFormat("%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); + Console::WriteLine(); + Console::WriteFormat("@ %s", OPENRCT2_TIMESTAMP); + Console::WriteLine(); + Console::WriteLine(); + + // Print current time + time(&timer); + tmInfo = localtime(&timer); + strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", tmInfo); + Console::WriteFormat("VERBOSE: time is %s", buffer); + Console::WriteLine(); + + // TODO Print other potential information (e.g. user, hardware) +} diff --git a/src/cmdline/ScreenshotCommands.cpp b/src/cmdline/ScreenshotCommands.cpp new file mode 100644 index 0000000000..2dc6a12c42 --- /dev/null +++ b/src/cmdline/ScreenshotCommands.cpp @@ -0,0 +1,9 @@ +#include "CommandLine.hpp" + +const CommandLineCommand CommandLine::ScreenshotCommands[] +{ + // Main commands + DefineCommand("", " [ ]", nullptr, nullptr), + DefineCommand("", " giant ", nullptr, nullptr), + CommandTableEnd +}; diff --git a/src/cmdline/SpriteCommands.cpp b/src/cmdline/SpriteCommands.cpp new file mode 100644 index 0000000000..c7f62dd410 --- /dev/null +++ b/src/cmdline/SpriteCommands.cpp @@ -0,0 +1,25 @@ +#include "CommandLine.hpp" + +static const char * _mode; + +static const CommandLineOptionDefinition SpriteOptions[] +{ + { CMDLINE_TYPE_STRING, &_mode, 'm', "mode", "the type of sprite conversion " }, + OptionTableEnd +}; + +static exitcode_t Handle(CommandLineArgEnumerator *argEnumerator); + +const CommandLineCommand CommandLine::SpriteCommands[] +{ + // Main commands + DefineCommand("details", " [idx]", SpriteOptions, Handle), + DefineCommand("export", " ", SpriteOptions, Handle), + DefineCommand("build", " [silent]", SpriteOptions, Handle), + CommandTableEnd +}; + +static exitcode_t Handle(CommandLineArgEnumerator *argEnumerator) +{ + return EXITCODE_OK; +} diff --git a/src/core/Console.cpp b/src/core/Console.cpp index e8e939239b..e4cde07de9 100644 --- a/src/core/Console.cpp +++ b/src/core/Console.cpp @@ -25,6 +25,15 @@ namespace Console } } + void WriteFormat(const utf8 * format, ...) + { + va_list args; + + va_start(args, format); + vfprintf(stdout, format, args); + va_end(args); + } + void WriteLine() { puts(""); diff --git a/src/core/Console.hpp b/src/core/Console.hpp index f1322f31ec..b9e30309f6 100644 --- a/src/core/Console.hpp +++ b/src/core/Console.hpp @@ -10,6 +10,7 @@ namespace Console void Write(char c); void Write(const utf8 * str); void WriteSpace(size_t count); + void WriteFormat(const utf8 * format, ...); void WriteLine(); void WriteLine(const utf8 * str); void WriteError(char c); diff --git a/src/core/String.cpp b/src/core/String.cpp new file mode 100644 index 0000000000..3c63bc3f9f --- /dev/null +++ b/src/core/String.cpp @@ -0,0 +1,106 @@ +extern "C" +{ + #include "../localisation/localisation.h" + #include "../util/util.h" +} + +#include "Math.hpp" +#include "Memory.hpp" +#include "String.hpp" + +namespace String +{ + bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase) + { + if (a == b) return true; + if (a == nullptr || b == nullptr) return false; + + if (ignoreCase) + { + return _strcmpi(a, b) == 0; + } + else + { + return strcmp(a, b) == 0; + } + } + + size_t LengthOf(const utf8 * str) + { + return utf8_length(str); + } + + size_t SizeOf(const utf8 * str) + { + return strlen(str); + } + + utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src) + { + return safe_strncpy(buffer, src, bufferSize); + } + + utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src, size_t srcSize) + { + utf8 * dst = buffer; + size_t minSize = Math::Min(bufferSize - 1, srcSize); + for (size_t i = 0; i < minSize; i++) + { + *dst++ = *src; + if (*src == '\0') break; + *src++; + } + *dst = '\0'; + return buffer; + } + + utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src) + { + return safe_strcat(buffer, src, bufferSize); + } + + utf8 * Format(utf8 * buffer, size_t bufferSize, const utf8 * format, ...) + { + va_list args; + + va_start(args, format); + vsnprintf(buffer, bufferSize, format, args); + va_end(args); + + // Terminate buffer in case formatted string overflowed + buffer[bufferSize - 1] = '\0'; + + return buffer; + } + + utf8 * AppendFormat(utf8 * buffer, size_t bufferSize, const utf8 * format, ...) + { + va_list args; + + utf8 * dst = buffer; + size_t i; + for (i = 0; i < bufferSize; i++) + { + if (*dst == '\0') break; + dst++; + } + + if (i < bufferSize - 1) + { + va_start(args, format); + vsnprintf(buffer, bufferSize - i - 1, format, args); + va_end(args); + + // Terminate buffer in case formatted string overflowed + buffer[bufferSize - 1] = '\0'; + } + + return buffer; + } + + utf8 * Duplicate(const utf8 * src) + { + size_t srcSize = SizeOf(src); + return Memory::DuplicateArray(src, srcSize + 1); + } +} diff --git a/src/core/String.hpp b/src/core/String.hpp index 5856263bef..ded9ec6f57 100644 --- a/src/core/String.hpp +++ b/src/core/String.hpp @@ -3,105 +3,17 @@ extern "C" { #include "../common.h" - #include "../localisation/localisation.h" - #include "../util/util.h" } -#include "Memory.hpp" - namespace String { - bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase = false) - { - if (a == b) return true; - if (a == nullptr || b == nullptr) return false; - - if (ignoreCase) - { - return _strcmpi(a, b) == 0; - } - else - { - return strcmp(a, b) == 0; - } - } - - size_t LengthOf(const utf8 * str) - { - return utf8_length(str); - } - - size_t SizeOf(const utf8 * str) - { - return strlen(str); - } - - utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src) - { - return safe_strncpy(buffer, src, bufferSize); - } - - utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src, size_t srcSize) - { - utf8 * dst = buffer; - size_t minSize = Math::Min(bufferSize - 1, srcSize); - for (size_t i = 0; i < minSize; i++) - { - *dst++ = *src; - if (*src == '\0') break; - *src++; - } - *dst = '\0'; - return buffer; - } - - utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src) - { - return safe_strcat(buffer, src, bufferSize); - } - - utf8 * Format(utf8 * buffer, size_t bufferSize, const utf8 * format, ...) - { - va_list args; - - va_start(args, format); - vsnprintf(buffer, bufferSize, format, args); - va_end(args); - - // Terminate buffer in case formatted string overflowed - buffer[bufferSize - 1] = '\0'; - - return buffer; - } - - utf8 * AppendFormat(utf8 * buffer, size_t bufferSize, const utf8 * format, ...) - { - va_list args; - - utf8 * dst = buffer; - size_t i; - for (i = 0; i < bufferSize; i++) - { - if (*dst == '\0') break; - dst++; - } - - if (i < bufferSize - 1) - { - va_start(args, format); - vsnprintf(buffer, bufferSize - i - 1, format, args); - va_end(args); - - // Terminate buffer in case formatted string overflowed - buffer[bufferSize - 1] = '\0'; - } - - return buffer; - } - - utf8 * Duplicate(const utf8 * src) - { - size_t srcSize = SizeOf(src); - return Memory::DuplicateArray(src, srcSize + 1); - } + bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase = false); + size_t LengthOf(const utf8 * str); + size_t SizeOf(const utf8 * str); + utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src); + utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src, size_t srcSize); + utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src); + utf8 * Format(utf8 * buffer, size_t bufferSize, const utf8 * format, ...); + utf8 * AppendFormat(utf8 * buffer, size_t bufferSize, const utf8 * format, ...); + utf8 * Duplicate(const utf8 * src); } diff --git a/src/openrct2.c b/src/openrct2.c index 469a610c29..5bc9bc39fc 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -283,6 +283,9 @@ void openrct2_launch() #ifndef DISABLE_NETWORK if (gNetworkStart == NETWORK_MODE_SERVER) { + if (gNetworkStartPort == 0) { + gNetworkStartPort = gConfigNetwork.default_port; + } network_begin_server(gNetworkStartPort); } #endif // DISABLE_NETWORK @@ -298,6 +301,9 @@ void openrct2_launch() #ifndef DISABLE_NETWORK if (gNetworkStart == NETWORK_MODE_CLIENT) { + if (gNetworkStartPort == 0) { + gNetworkStartPort = gConfigNetwork.default_port; + } network_begin_client(gNetworkStartHost, gNetworkStartPort); } #endif // DISABLE_NETWORK diff --git a/src/openrct2.h b/src/openrct2.h index 5c7eda680c..7683857f1c 100644 --- a/src/openrct2.h +++ b/src/openrct2.h @@ -39,6 +39,12 @@ extern utf8 gCustomOpenrctDataPath[MAX_PATH]; extern bool gOpenRCT2Headless; extern bool gOpenRCT2ShowChangelog; +#ifndef DISABLE_NETWORK +extern int gNetworkStart; +extern char gNetworkStartHost[128]; +extern int gNetworkStartPort; +#endif + void openrct2_write_full_version_info(utf8 *buffer, size_t bufferSize); bool openrct2_initialise(); void openrct2_launch();