mirror of https://github.com/OpenRCT2/OpenRCT2.git
new-argparse: implement argument and option parsing
This commit is contained in:
parent
14a266c177
commit
9d98147b75
|
@ -26,9 +26,10 @@
|
|||
<ClCompile Include="src\cheats.c" />
|
||||
<ClCompile Include="src\cmdline.c" />
|
||||
<ClCompile Include="src\cmdline\CommandLine.cpp" />
|
||||
<ClCompile Include="src\cmdline\CommandLineDefinitions.cpp" />
|
||||
<ClCompile Include="src\cmdline\RootCommands.cpp" />
|
||||
<ClCompile Include="src\cmdline_sprite.c" />
|
||||
<ClCompile Include="src\config.c" />
|
||||
<ClCompile Include="src\core\Console.cpp" />
|
||||
<ClCompile Include="src\core\Stopwatch.cpp" />
|
||||
<ClCompile Include="src\cursors.c" />
|
||||
<ClCompile Include="src\diagnostic.c" />
|
||||
|
|
|
@ -564,8 +564,9 @@
|
|||
<ClCompile Include="src\argparse\argparse.c">
|
||||
<Filter>Source\argparse</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\cmdline\CommandLineDefinitions.cpp" />
|
||||
<ClCompile Include="src\cmdline\CommandLine.cpp" />
|
||||
<ClCompile Include="src\cmdline\RootCommands.cpp" />
|
||||
<ClCompile Include="src\core\Console.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\management\award.h">
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
|
||||
<LocalDebuggerCommandArguments>--port=233</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
|
||||
|
|
|
@ -8,6 +8,8 @@ extern "C"
|
|||
#include "../core/String.hpp"
|
||||
#include "CommandLine.hpp"
|
||||
|
||||
#pragma region CommandLineArgEnumerator
|
||||
|
||||
CommandLineArgEnumerator::CommandLineArgEnumerator(const char * const * arguments, int count)
|
||||
{
|
||||
_arguments = arguments;
|
||||
|
@ -20,6 +22,19 @@ void CommandLineArgEnumerator::Reset()
|
|||
_index = 0;
|
||||
}
|
||||
|
||||
bool CommandLineArgEnumerator::Backtrack()
|
||||
{
|
||||
if (_index > 0)
|
||||
{
|
||||
_index--;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CommandLineArgEnumerator::TryPop()
|
||||
{
|
||||
if (_index < _count)
|
||||
|
@ -71,6 +86,8 @@ bool CommandLineArgEnumerator::TryPopString(const char * * result)
|
|||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
namespace CommandLine
|
||||
{
|
||||
constexpr const char * HelpText = "openrct2 -ha shows help for all commands. "
|
||||
|
@ -80,6 +97,13 @@ namespace CommandLine
|
|||
static void PrintExamples(const CommandLineExample *examples);
|
||||
static utf8 * GetOptionCaption(utf8 * buffer, size_t bufferSize, const CommandLineOptionDefinition *option);
|
||||
|
||||
static const CommandLineOptionDefinition * FindOption(const CommandLineOptionDefinition * options, char shortName);
|
||||
static const CommandLineOptionDefinition * FindOption(const CommandLineOptionDefinition * options, const char * longName);
|
||||
|
||||
static bool ParseShortOption(const CommandLineOptionDefinition * options, CommandLineArgEnumerator *argEnumerator, const char *argument);
|
||||
static bool ParseLongOption(const CommandLineOptionDefinition * options, CommandLineArgEnumerator * argEnumerator, const char * argument);
|
||||
static bool ParseOptionValue(const CommandLineOptionDefinition * option, const char * valueString);
|
||||
|
||||
void PrintHelp()
|
||||
{
|
||||
const CommandLineCommand * command;
|
||||
|
@ -215,19 +239,23 @@ namespace CommandLine
|
|||
return buffer;
|
||||
}
|
||||
|
||||
const CommandLineCommand * FindCommandFor(const CommandLineCommand * commands, const char * const * arguments, int count)
|
||||
void PrintUsageFor(const char * command)
|
||||
{
|
||||
// Check if there are any arguments
|
||||
if (count == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check if options have started
|
||||
const char * firstArgument = arguments[0];
|
||||
}
|
||||
|
||||
const CommandLineCommand * FindCommandFor(const CommandLineCommand * commands, CommandLineArgEnumerator *argEnumerator)
|
||||
{
|
||||
// Check if end of arguments or options have started
|
||||
const char * firstArgument;
|
||||
if (!argEnumerator->TryPopString(&firstArgument))
|
||||
{
|
||||
return commands;
|
||||
}
|
||||
if (firstArgument[0] == '-')
|
||||
{
|
||||
return nullptr;
|
||||
argEnumerator->Backtrack();
|
||||
return commands;
|
||||
}
|
||||
|
||||
// Search through defined commands for one that matches
|
||||
|
@ -250,25 +278,241 @@ namespace CommandLine
|
|||
else
|
||||
{
|
||||
// Recurse for the sub command table
|
||||
return FindCommandFor(command->SubCommands, &arguments[1], count - 1);
|
||||
return FindCommandFor(command->SubCommands, argEnumerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLineDisplayUsageFor(const char * command)
|
||||
{
|
||||
static bool ParseOptions(const CommandLineOptionDefinition * options, CommandLineArgEnumerator *argEnumerator)
|
||||
{
|
||||
const char * argument;
|
||||
if (argEnumerator->TryPopString(&argument))
|
||||
{
|
||||
if (argument[0] == '-')
|
||||
{
|
||||
if (argument[1] == '-')
|
||||
{
|
||||
if (!ParseLongOption(options, argEnumerator, &argument[2]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ParseShortOption(options, argEnumerator, argument))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console::WriteLineError("All options must be passed at the end of the command line.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ParseLongOption(const CommandLineOptionDefinition * options,
|
||||
CommandLineArgEnumerator *argEnumerator,
|
||||
const char *argument)
|
||||
{
|
||||
// Get just the option name
|
||||
char optionName[64];
|
||||
const char * equalsCh = strchr(argument, '=');
|
||||
if (equalsCh != nullptr)
|
||||
{
|
||||
String::Set(optionName, sizeof(optionName), argument, equalsCh - argument);
|
||||
}
|
||||
else
|
||||
{
|
||||
String::Set(optionName, sizeof(optionName), argument);
|
||||
}
|
||||
|
||||
// Find a matching option definition
|
||||
const CommandLineOptionDefinition * option = FindOption(options, optionName);
|
||||
if (option == nullptr)
|
||||
{
|
||||
Console::WriteError("Unknown option: --");
|
||||
Console::WriteLineError(optionName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (equalsCh == nullptr)
|
||||
{
|
||||
if (option->Type == CMDLINE_TYPE_SWITCH)
|
||||
{
|
||||
ParseOptionValue(option, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char * valueString = nullptr;
|
||||
if (!argEnumerator->TryPopString(&valueString))
|
||||
{
|
||||
Console::WriteError("Expected value for option: ");
|
||||
Console::WriteLineError(optionName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ParseOptionValue(option, valueString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (option->Type == CMDLINE_TYPE_SWITCH)
|
||||
{
|
||||
Console::WriteError("Option is a switch: ");
|
||||
Console::WriteLineError(optionName);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ParseOptionValue(option, equalsCh + 1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ParseShortOption(const CommandLineOptionDefinition * options,
|
||||
CommandLineArgEnumerator *argEnumerator,
|
||||
const char *argument)
|
||||
{
|
||||
const CommandLineOptionDefinition * option = nullptr;
|
||||
|
||||
const char * shortOption = &argument[1];
|
||||
for (; *shortOption != '\0'; shortOption++)
|
||||
{
|
||||
option = FindOption(options, shortOption[0]);
|
||||
if (option == nullptr)
|
||||
{
|
||||
Console::WriteError("Unknown option: -");
|
||||
Console::WriteError(shortOption[0]);
|
||||
Console::WriteLineError();
|
||||
return false;
|
||||
}
|
||||
if (option->Type == CMDLINE_TYPE_SWITCH)
|
||||
{
|
||||
if (!ParseOptionValue(option, nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (shortOption[1] != '\0')
|
||||
{
|
||||
if (!ParseOptionValue(option, &shortOption[1]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (option != nullptr && option->Type != CMDLINE_TYPE_SWITCH)
|
||||
{
|
||||
const char * valueString = nullptr;
|
||||
if (!argEnumerator->TryPopString(&valueString))
|
||||
{
|
||||
Console::WriteError("Expected value for option: ");
|
||||
Console::WriteError(option->ShortName);
|
||||
Console::WriteLineError();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ParseOptionValue(option, valueString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ParseOptionValue(const CommandLineOptionDefinition * option, const char * valueString)
|
||||
{
|
||||
if (option->OutAddress == nullptr) return true;
|
||||
|
||||
switch (option->Type) {
|
||||
case CMDLINE_TYPE_SWITCH:
|
||||
*((bool *)option->OutAddress) = true;
|
||||
return true;
|
||||
case CMDLINE_TYPE_INTEGER:
|
||||
*((sint32 *)option->OutAddress) = (sint32)atol(valueString);
|
||||
return true;
|
||||
case CMDLINE_TYPE_REAL:
|
||||
*((float *)option->OutAddress) = (float)atof(valueString);
|
||||
return true;
|
||||
case CMDLINE_TYPE_STRING:
|
||||
*((utf8 * *)option->OutAddress) = String::Duplicate(valueString);
|
||||
return true;
|
||||
default:
|
||||
Console::WriteError("Unknown CMDLINE_TYPE for: ");
|
||||
Console::WriteLineError(option->LongName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const CommandLineOptionDefinition * FindOption(const CommandLineOptionDefinition * options, char shortName)
|
||||
{
|
||||
for (const CommandLineOptionDefinition * option = options; option->Type != 255; option++)
|
||||
{
|
||||
if (option->ShortName == shortName)
|
||||
{
|
||||
return option;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CommandLineOptionDefinition * FindOption(const CommandLineOptionDefinition * options, const char * longName)
|
||||
{
|
||||
for (const CommandLineOptionDefinition * option = options; option->Type != 255; option++)
|
||||
{
|
||||
if (String::Equals(option->LongName, longName))
|
||||
{
|
||||
return option;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int cmdline_run(const char * * argv, int argc)
|
||||
{
|
||||
CommandLine::PrintHelp();
|
||||
return 0;
|
||||
auto argEnumerator = CommandLineArgEnumerator(argv, argc);
|
||||
|
||||
// Pop process path
|
||||
argEnumerator.TryPop();
|
||||
|
||||
const CommandLineCommand * command = CommandLine::FindCommandFor(CommandLine::RootCommands, &argEnumerator);
|
||||
if (command->Options != nullptr)
|
||||
{
|
||||
auto argEnumeratorForOptions = CommandLineArgEnumerator(argEnumerator);
|
||||
if (!CommandLine::ParseOptions(command->Options, &argEnumeratorForOptions))
|
||||
{
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
}
|
||||
if (command == CommandLine::RootCommands || command->Func == nullptr)
|
||||
{
|
||||
return CommandLine::HandleCommandDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
return command->Func(&argEnumerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
CommandLineArgEnumerator(const char * const * arguments, int count);
|
||||
|
||||
void Reset();
|
||||
bool Backtrack();
|
||||
bool TryPop();
|
||||
bool TryPopInteger(sint32 * result);
|
||||
bool TryPopReal(float * result);
|
||||
|
@ -31,6 +32,13 @@ public:
|
|||
typedef int exitcode_t;
|
||||
typedef exitcode_t (*CommandLineFunc)(CommandLineArgEnumerator *);
|
||||
|
||||
enum
|
||||
{
|
||||
EXITCODE_FAIL = -1,
|
||||
EXITCODE_OK = 0,
|
||||
EXITCODE_CONTINUE = 1,
|
||||
};
|
||||
|
||||
struct CommandLineExample
|
||||
{
|
||||
const char * Arguments;
|
||||
|
@ -72,12 +80,13 @@ constexpr char NAC = '\0';
|
|||
#define DefineCommand(name, params, options, func) { name, params, options, NULL, func }
|
||||
#define DefineSubCommand(name, subcommandtable) { name, "", NULL, subcommandtable, NULL }
|
||||
|
||||
void CommandLineDisplayUsageFor(const char * command);
|
||||
|
||||
extern const CommandLineCommand RootCommands[];
|
||||
extern const CommandLineExample RootExamples[];
|
||||
|
||||
namespace CommandLine
|
||||
{
|
||||
extern const CommandLineCommand RootCommands[];
|
||||
extern const CommandLineExample RootExamples[];
|
||||
|
||||
void PrintHelp();
|
||||
void PrintUsageFor(const char * command);
|
||||
|
||||
exitcode_t HandleCommandDefault();
|
||||
}
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
#include "CommandLine.hpp"
|
||||
|
||||
const CommandLineCommand * ScreenshotCommandTable;
|
||||
const CommandLineCommand * SpriteCommandTable;
|
||||
|
||||
static bool _help;
|
||||
static bool _version;
|
||||
static bool _noInstall;
|
||||
|
||||
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, nullptr, NAC, "no-install", "show information about " OPENRCT2_NAME },
|
||||
{ CMDLINE_TYPE_SWITCH, nullptr, NAC, "verbose", "log verbose messages" },
|
||||
{ CMDLINE_TYPE_SWITCH, nullptr, NAC, "headless", "run " OPENRCT2_NAME " headless" },
|
||||
{ CMDLINE_TYPE_INTEGER, nullptr, NAC, "port", "port to use for hosting or joining a server" },
|
||||
{ CMDLINE_TYPE_STRING, nullptr, NAC, "user-data-path", "path to the user data directory (containing config.ini)" },
|
||||
{ CMDLINE_TYPE_STRING, nullptr, NAC, "openrct-data-path", "path to the OpenRCT2 data directory (containing languages)" },
|
||||
OptionTableEnd
|
||||
};
|
||||
|
||||
const CommandLineCommand RootCommands[]
|
||||
{
|
||||
// Main commands
|
||||
DefineCommand("", "<uri>", StandardOptions, nullptr),
|
||||
DefineCommand("intro", "", StandardOptions, nullptr),
|
||||
DefineCommand("host", "<uri>", StandardOptions, nullptr),
|
||||
DefineCommand("join", "<hostname>", StandardOptions, nullptr),
|
||||
|
||||
// Sub-commands
|
||||
DefineSubCommand("screenshot", ScreenshotCommandTable),
|
||||
DefineSubCommand("sprite", SpriteCommandTable ),
|
||||
|
||||
CommandTableEnd
|
||||
};
|
||||
|
||||
const CommandLineExample RootExamples[]
|
||||
{
|
||||
{ "./my_park.sv6", "open a saved park" },
|
||||
{ "./SnowyPark.sc6", "install and open a scenario" },
|
||||
{ "./ShuttleLoop.td6", "install a track" },
|
||||
{ "http:/openrct2.website/files/SnowyPark.sv6", "download and open a saved park" },
|
||||
{ "host ./my_park.sv6 --port 11753 --headless", "run a headless server for a saved park" },
|
||||
ExampleTableEnd
|
||||
};
|
||||
|
||||
void HandleNoCommand(CommandLineArgEnumerator * enumerator)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void HandleCommandIntro(CommandLineArgEnumerator * enumerator)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void HandleCommandHost(CommandLineArgEnumerator * enumerator)
|
||||
{
|
||||
const char * parkUri;
|
||||
|
||||
if (!enumerator->TryPopString(&parkUri))
|
||||
{
|
||||
fprintf(stderr, "Expected path or URL to a saved park.");
|
||||
CommandLineDisplayUsageFor("host");
|
||||
}
|
||||
}
|
||||
|
||||
void HandleCommandJoin(CommandLineArgEnumerator * enumerator)
|
||||
{
|
||||
const char * hostname;
|
||||
|
||||
if (!enumerator->TryPopString(&hostname))
|
||||
{
|
||||
fprintf(stderr, "Expected a hostname or IP address to the server to connect to.");
|
||||
CommandLineDisplayUsageFor("join");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const CommandLineCommand ScreenshotCommands[]
|
||||
{
|
||||
// Main commands
|
||||
DefineCommand("", "<file> <output_image> <width> <height> [<x> <y> <zoom> <rotation>]", nullptr, nullptr),
|
||||
DefineCommand("", "<file> <output_image> giant <zoom> <rotation>", nullptr, nullptr),
|
||||
CommandTableEnd
|
||||
};
|
||||
|
||||
const CommandLineOptionDefinition SpriteOptions[]
|
||||
{
|
||||
{ CMDLINE_TYPE_STRING, nullptr, 'm', "mode", "the type of sprite conversion <default|simple|dithering>" },
|
||||
OptionTableEnd
|
||||
};
|
||||
|
||||
const CommandLineCommand SpriteCommands[]
|
||||
{
|
||||
// Main commands
|
||||
DefineCommand("details", "<spritefile> [idx]", SpriteOptions, nullptr),
|
||||
DefineCommand("export", "<spritefile> <idx> <output>", SpriteOptions, nullptr),
|
||||
DefineCommand("build", "<spritefile> <resourcedir> [silent]", SpriteOptions, nullptr),
|
||||
CommandTableEnd
|
||||
};
|
|
@ -0,0 +1,157 @@
|
|||
#include "../core/Console.hpp"
|
||||
#include "CommandLine.hpp"
|
||||
|
||||
const CommandLineCommand * ScreenshotCommandTable;
|
||||
const CommandLineCommand * SpriteCommandTable;
|
||||
|
||||
static bool _help = false;
|
||||
static bool _version = false;
|
||||
static bool _noInstall = false;
|
||||
static bool _about = false;
|
||||
static bool _verbose = false;
|
||||
static bool _headless = false;
|
||||
static uint32 _port = 0;
|
||||
static utf8 * _userDataPath = nullptr;
|
||||
static utf8 * _openrctDataPath = nullptr;
|
||||
|
||||
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, &_verbose, NAC, "verbose", "log verbose messages" },
|
||||
{ CMDLINE_TYPE_SWITCH, &_headless, NAC, "headless", "run " OPENRCT2_NAME " headless" },
|
||||
{ CMDLINE_TYPE_INTEGER, &_port, NAC, "port", "port to use for hosting or joining a server" },
|
||||
{ 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 HandleCommandIntro(CommandLineArgEnumerator * enumerator);
|
||||
static exitcode_t HandleCommandHost(CommandLineArgEnumerator * enumerator);
|
||||
static exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator);
|
||||
|
||||
const CommandLineCommand CommandLine::RootCommands[]
|
||||
{
|
||||
// Main commands
|
||||
DefineCommand("", "<uri>", StandardOptions, HandleNoCommand ),
|
||||
DefineCommand("intro", "", StandardOptions, HandleCommandIntro),
|
||||
DefineCommand("host", "<uri>", StandardOptions, HandleCommandHost ),
|
||||
DefineCommand("join", "<hostname>", StandardOptions, HandleCommandJoin ),
|
||||
|
||||
// Sub-commands
|
||||
DefineSubCommand("screenshot", ScreenshotCommandTable),
|
||||
DefineSubCommand("sprite", SpriteCommandTable ),
|
||||
|
||||
CommandTableEnd
|
||||
};
|
||||
|
||||
static const CommandLineExample CommandLine::RootExamples[]
|
||||
{
|
||||
{ "./my_park.sv6", "open a saved park" },
|
||||
{ "./SnowyPark.sc6", "install and open a scenario" },
|
||||
{ "./ShuttleLoop.td6", "install a track" },
|
||||
{ "http:/openrct2.website/files/SnowyPark.sv6", "download and open a saved park" },
|
||||
{ "host ./my_park.sv6 --port 11753 --headless", "run a headless server for a saved park" },
|
||||
ExampleTableEnd
|
||||
};
|
||||
|
||||
exitcode_t CommandLine::HandleCommandDefault()
|
||||
{
|
||||
if (_help)
|
||||
{
|
||||
CommandLine::PrintHelp();
|
||||
return EXITCODE_OK;
|
||||
}
|
||||
|
||||
return EXITCODE_CONTINUE;
|
||||
}
|
||||
|
||||
exitcode_t HandleNoCommand(CommandLineArgEnumerator * enumerator)
|
||||
{
|
||||
exitcode_t result = CommandLine::HandleCommandDefault();
|
||||
if (result != EXITCODE_CONTINUE)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Process URI
|
||||
|
||||
return EXITCODE_CONTINUE;
|
||||
}
|
||||
|
||||
exitcode_t HandleCommandIntro(CommandLineArgEnumerator * enumerator)
|
||||
{
|
||||
exitcode_t result = CommandLine::HandleCommandDefault();
|
||||
if (result != EXITCODE_CONTINUE)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return EXITCODE_CONTINUE;
|
||||
}
|
||||
|
||||
exitcode_t HandleCommandHost(CommandLineArgEnumerator * enumerator)
|
||||
{
|
||||
const char * parkUri;
|
||||
|
||||
exitcode_t result = CommandLine::HandleCommandDefault();
|
||||
if (result != EXITCODE_CONTINUE)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!enumerator->TryPopString(&parkUri))
|
||||
{
|
||||
Console::WriteLineError("Expected path or URL to a saved park.");
|
||||
CommandLine::PrintUsageFor("host");
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
|
||||
return EXITCODE_CONTINUE;
|
||||
}
|
||||
|
||||
exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator)
|
||||
{
|
||||
const char * hostname;
|
||||
|
||||
exitcode_t result = CommandLine::HandleCommandDefault();
|
||||
if (result != EXITCODE_CONTINUE)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!enumerator->TryPopString(&hostname))
|
||||
{
|
||||
Console::WriteLineError("Expected a hostname or IP address to the server to connect to.");
|
||||
CommandLine::PrintUsageFor("join");
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
|
||||
return EXITCODE_CONTINUE;
|
||||
}
|
||||
|
||||
const CommandLineCommand ScreenshotCommands[]
|
||||
{
|
||||
// Main commands
|
||||
DefineCommand("", "<file> <output_image> <width> <height> [<x> <y> <zoom> <rotation>]", nullptr, nullptr),
|
||||
DefineCommand("", "<file> <output_image> giant <zoom> <rotation>", nullptr, nullptr),
|
||||
CommandTableEnd
|
||||
};
|
||||
|
||||
const CommandLineOptionDefinition SpriteOptions[]
|
||||
{
|
||||
{ CMDLINE_TYPE_STRING, nullptr, 'm', "mode", "the type of sprite conversion <default|simple|dithering>" },
|
||||
OptionTableEnd
|
||||
};
|
||||
|
||||
const CommandLineCommand SpriteCommands[]
|
||||
{
|
||||
// Main commands
|
||||
DefineCommand("details", "<spritefile> [idx]", SpriteOptions, nullptr),
|
||||
DefineCommand("export", "<spritefile> <idx> <output>", SpriteOptions, nullptr),
|
||||
DefineCommand("build", "<spritefile> <resourcedir> [silent]", SpriteOptions, nullptr),
|
||||
CommandTableEnd
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
extern "C"
|
||||
{
|
||||
#include "../platform/platform.h"
|
||||
}
|
||||
|
||||
#include "Console.hpp"
|
||||
|
||||
namespace Console
|
||||
{
|
||||
void Write(char c)
|
||||
{
|
||||
fputc(c, stdout);
|
||||
}
|
||||
|
||||
void Write(const utf8 * str)
|
||||
{
|
||||
fputs(str, stdout);
|
||||
}
|
||||
|
||||
void WriteSpace(size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
Write(' ');
|
||||
}
|
||||
}
|
||||
|
||||
void WriteLine()
|
||||
{
|
||||
puts("");
|
||||
}
|
||||
|
||||
void WriteLine(const utf8 * str)
|
||||
{
|
||||
puts(str);
|
||||
}
|
||||
|
||||
void WriteError(char c)
|
||||
{
|
||||
fputc(c, stderr);
|
||||
}
|
||||
|
||||
void WriteError(const utf8 * str)
|
||||
{
|
||||
fputs(str, stderr);
|
||||
}
|
||||
|
||||
void WriteLineError()
|
||||
{
|
||||
fputs(platform_get_new_line(), stderr);
|
||||
}
|
||||
|
||||
void WriteLineError(const utf8 * str)
|
||||
{
|
||||
fputs(str, stderr);
|
||||
WriteLineError();
|
||||
}
|
||||
}
|
|
@ -7,26 +7,13 @@ extern "C"
|
|||
|
||||
namespace Console
|
||||
{
|
||||
void Write(const utf8 * str)
|
||||
{
|
||||
fputs(str, stdout);
|
||||
}
|
||||
|
||||
void WriteSpace(size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
fputc(' ', stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteLine()
|
||||
{
|
||||
puts("");
|
||||
}
|
||||
|
||||
void WriteLine(const utf8 * str)
|
||||
{
|
||||
puts(str);
|
||||
}
|
||||
void Write(char c);
|
||||
void Write(const utf8 * str);
|
||||
void WriteSpace(size_t count);
|
||||
void WriteLine();
|
||||
void WriteLine(const utf8 * str);
|
||||
void WriteError(char c);
|
||||
void WriteError(const utf8 * str);
|
||||
void WriteLineError();
|
||||
void WriteLineError(const utf8 * str);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ extern "C"
|
|||
#include "../util/util.h"
|
||||
}
|
||||
|
||||
#include "Memory.hpp"
|
||||
|
||||
namespace String
|
||||
{
|
||||
bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase = false)
|
||||
|
@ -34,6 +36,25 @@ namespace String
|
|||
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);
|
||||
|
@ -77,4 +98,10 @@ namespace String
|
|||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
utf8 * Duplicate(const utf8 * src)
|
||||
{
|
||||
size_t srcSize = SizeOf(src);
|
||||
return Memory::DuplicateArray(src, srcSize + 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta
|
|||
}
|
||||
free(argv);
|
||||
|
||||
if (runGame) {
|
||||
if (runGame == 1) {
|
||||
openrct2_launch();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue