mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
new-argparse: add basic definitions and help display
This commit is contained in:
@@ -25,6 +25,8 @@
|
|||||||
<ClCompile Include="src\audio\mixer.cpp" />
|
<ClCompile Include="src\audio\mixer.cpp" />
|
||||||
<ClCompile Include="src\cheats.c" />
|
<ClCompile Include="src\cheats.c" />
|
||||||
<ClCompile Include="src\cmdline.c" />
|
<ClCompile Include="src\cmdline.c" />
|
||||||
|
<ClCompile Include="src\cmdline\CommandLine.cpp" />
|
||||||
|
<ClCompile Include="src\cmdline\CommandLineDefinitions.cpp" />
|
||||||
<ClCompile Include="src\cmdline_sprite.c" />
|
<ClCompile Include="src\cmdline_sprite.c" />
|
||||||
<ClCompile Include="src\config.c" />
|
<ClCompile Include="src\config.c" />
|
||||||
<ClCompile Include="src\core\Stopwatch.cpp" />
|
<ClCompile Include="src\core\Stopwatch.cpp" />
|
||||||
@@ -191,8 +193,10 @@
|
|||||||
<ClInclude Include="src\audio\mixer.h" />
|
<ClInclude Include="src\audio\mixer.h" />
|
||||||
<ClInclude Include="src\cheats.h" />
|
<ClInclude Include="src\cheats.h" />
|
||||||
<ClInclude Include="src\cmdline.h" />
|
<ClInclude Include="src\cmdline.h" />
|
||||||
|
<ClInclude Include="src\cmdline\CommandLine.hpp" />
|
||||||
<ClInclude Include="src\common.h" />
|
<ClInclude Include="src\common.h" />
|
||||||
<ClInclude Include="src\config.h" />
|
<ClInclude Include="src\config.h" />
|
||||||
|
<ClInclude Include="src\core\Console.hpp" />
|
||||||
<ClInclude Include="src\core\Exception.hpp" />
|
<ClInclude Include="src\core\Exception.hpp" />
|
||||||
<ClInclude Include="src\core\FileStream.hpp" />
|
<ClInclude Include="src\core\FileStream.hpp" />
|
||||||
<ClInclude Include="src\core\IDisposable.hpp" />
|
<ClInclude Include="src\core\IDisposable.hpp" />
|
||||||
@@ -201,6 +205,7 @@
|
|||||||
<ClInclude Include="src\core\Memory.hpp" />
|
<ClInclude Include="src\core\Memory.hpp" />
|
||||||
<ClInclude Include="src\core\stopwatch.h" />
|
<ClInclude Include="src\core\stopwatch.h" />
|
||||||
<ClInclude Include="src\core\Stopwatch.hpp" />
|
<ClInclude Include="src\core\Stopwatch.hpp" />
|
||||||
|
<ClInclude Include="src\core\String.hpp" />
|
||||||
<ClInclude Include="src\core\StringBuilder.hpp" />
|
<ClInclude Include="src\core\StringBuilder.hpp" />
|
||||||
<ClInclude Include="src\core\StringReader.hpp" />
|
<ClInclude Include="src\core\StringReader.hpp" />
|
||||||
<ClInclude Include="src\core\Util.hpp" />
|
<ClInclude Include="src\core\Util.hpp" />
|
||||||
|
|||||||
@@ -564,6 +564,8 @@
|
|||||||
<ClCompile Include="src\argparse\argparse.c">
|
<ClCompile Include="src\argparse\argparse.c">
|
||||||
<Filter>Source\argparse</Filter>
|
<Filter>Source\argparse</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\cmdline\CommandLineDefinitions.cpp" />
|
||||||
|
<ClCompile Include="src\cmdline\CommandLine.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\management\award.h">
|
<ClInclude Include="src\management\award.h">
|
||||||
@@ -860,5 +862,8 @@
|
|||||||
<ClInclude Include="src\argparse\argparse.h">
|
<ClInclude Include="src\argparse\argparse.h">
|
||||||
<Filter>Source\argparse</Filter>
|
<Filter>Source\argparse</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\cmdline\CommandLine.hpp" />
|
||||||
|
<ClInclude Include="src\core\String.hpp" />
|
||||||
|
<ClInclude Include="src\core\Console.hpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -70,7 +70,7 @@ static const char *const usage[] = {
|
|||||||
* will then terminate before any initialisation has even been done.
|
* will then terminate before any initialisation has even been done.
|
||||||
* @returns 1 if the game should run, otherwise 0.
|
* @returns 1 if the game should run, otherwise 0.
|
||||||
*/
|
*/
|
||||||
int cmdline_run(const char **argv, int argc)
|
int cmdline_run_old(const char **argv, int argc)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
int version = 0, headless = 0, verbose = 0, width = 0, height = 0, port = 0;
|
int version = 0, headless = 0, verbose = 0, width = 0, height = 0, port = 0;
|
||||||
|
|||||||
274
src/cmdline/CommandLine.cpp
Normal file
274
src/cmdline/CommandLine.cpp
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "../platform/platform.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "../core/Console.hpp"
|
||||||
|
#include "../core/Math.hpp"
|
||||||
|
#include "../core/String.hpp"
|
||||||
|
#include "CommandLine.hpp"
|
||||||
|
|
||||||
|
CommandLineArgEnumerator::CommandLineArgEnumerator(const char * const * arguments, int count)
|
||||||
|
{
|
||||||
|
_arguments = arguments;
|
||||||
|
_count = count;
|
||||||
|
_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandLineArgEnumerator::Reset()
|
||||||
|
{
|
||||||
|
_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandLineArgEnumerator::TryPop()
|
||||||
|
{
|
||||||
|
if (_index < _count)
|
||||||
|
{
|
||||||
|
_index++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandLineArgEnumerator::TryPopInteger(sint32 * result)
|
||||||
|
{
|
||||||
|
char const * arg;
|
||||||
|
if (TryPopString(&arg))
|
||||||
|
{
|
||||||
|
*result = (sint32)atol(arg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandLineArgEnumerator::TryPopReal(float * result)
|
||||||
|
{
|
||||||
|
char const * arg;
|
||||||
|
if (TryPopString(&arg))
|
||||||
|
{
|
||||||
|
*result = (float)atof(arg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandLineArgEnumerator::TryPopString(const char * * result)
|
||||||
|
{
|
||||||
|
if (_index < _count)
|
||||||
|
{
|
||||||
|
*result = _arguments[_index];
|
||||||
|
_index++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CommandLine
|
||||||
|
{
|
||||||
|
constexpr const char * HelpText = "openrct2 -ha shows help for all commands. "
|
||||||
|
"openrct2 <command> -h will show help and details for a given command.";
|
||||||
|
|
||||||
|
static void PrintOptions(const CommandLineOptionDefinition *options);
|
||||||
|
static void PrintExamples(const CommandLineExample *examples);
|
||||||
|
static utf8 * GetOptionCaption(utf8 * buffer, size_t bufferSize, const CommandLineOptionDefinition *option);
|
||||||
|
|
||||||
|
void PrintHelp()
|
||||||
|
{
|
||||||
|
const CommandLineCommand * command;
|
||||||
|
size_t maxNameLength = 0;
|
||||||
|
size_t maxParamsLength = 0;
|
||||||
|
|
||||||
|
// Get the largest command name length and parameter length
|
||||||
|
for (command = RootCommands; 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++)
|
||||||
|
{
|
||||||
|
if (command != RootCommands)
|
||||||
|
{
|
||||||
|
Console::WriteSpace(usageStringLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::Write(command->Name);
|
||||||
|
Console::WriteSpace(maxNameLength - String::LengthOf(command->Name) + 1);
|
||||||
|
|
||||||
|
if (command->SubCommands == nullptr)
|
||||||
|
{
|
||||||
|
Console::Write(command->Parameters);
|
||||||
|
Console::WriteSpace(maxParamsLength - String::LengthOf(command->Parameters));
|
||||||
|
|
||||||
|
if (command->Options != nullptr)
|
||||||
|
{
|
||||||
|
Console::Write(" [options]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console::Write("...");
|
||||||
|
}
|
||||||
|
Console::WriteLine();
|
||||||
|
}
|
||||||
|
Console::WriteLine();
|
||||||
|
|
||||||
|
PrintOptions(RootCommands->Options);
|
||||||
|
PrintExamples(RootExamples);
|
||||||
|
|
||||||
|
Console::WriteLine(HelpText);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintOptions(const CommandLineOptionDefinition *options)
|
||||||
|
{
|
||||||
|
// Print options for main commands
|
||||||
|
size_t maxOptionLength = 0;
|
||||||
|
const CommandLineOptionDefinition * option = options;
|
||||||
|
for (; option->Type != 255; option++)
|
||||||
|
{
|
||||||
|
char buffer[128];
|
||||||
|
GetOptionCaption(buffer, sizeof(buffer), option);
|
||||||
|
size_t optionCaptionLength = String::LengthOf(buffer);
|
||||||
|
maxOptionLength = Math::Max(maxOptionLength, optionCaptionLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
option = RootCommands->Options;
|
||||||
|
for (; option->Type != 255; option++)
|
||||||
|
{
|
||||||
|
Console::WriteSpace(4);
|
||||||
|
|
||||||
|
char buffer[128];
|
||||||
|
GetOptionCaption(buffer, sizeof(buffer), option);
|
||||||
|
size_t optionCaptionLength = String::LengthOf(buffer);
|
||||||
|
Console::Write(buffer);
|
||||||
|
|
||||||
|
Console::WriteSpace(maxOptionLength - optionCaptionLength + 4);
|
||||||
|
Console::Write(option->Description);
|
||||||
|
Console::WriteLine();
|
||||||
|
}
|
||||||
|
Console::WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintExamples(const CommandLineExample *examples)
|
||||||
|
{
|
||||||
|
size_t maxArgumentsLength = 0;
|
||||||
|
|
||||||
|
const CommandLineExample * example;
|
||||||
|
for (example = examples; example->Arguments != nullptr; example++)
|
||||||
|
{
|
||||||
|
size_t argumentsLength = String::LengthOf(example->Arguments);
|
||||||
|
maxArgumentsLength = Math::Max(maxArgumentsLength, argumentsLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::WriteLine("examples:");
|
||||||
|
for (example = examples; example->Arguments != nullptr; example++)
|
||||||
|
{
|
||||||
|
Console::Write(" openrct2 ");
|
||||||
|
Console::Write(example->Arguments);
|
||||||
|
|
||||||
|
size_t argumentsLength = String::LengthOf(example->Arguments);
|
||||||
|
Console::WriteSpace(maxArgumentsLength - argumentsLength + 4);
|
||||||
|
Console::Write(example->Description);
|
||||||
|
Console::WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
static utf8 * GetOptionCaption(utf8 * buffer, size_t bufferSize, const CommandLineOptionDefinition *option)
|
||||||
|
{
|
||||||
|
buffer[0] = 0;
|
||||||
|
|
||||||
|
if (option->ShortName != '\0')
|
||||||
|
{
|
||||||
|
String::AppendFormat(buffer, bufferSize, "-%c, ", option->ShortName);
|
||||||
|
}
|
||||||
|
|
||||||
|
String::Append(buffer, bufferSize, "--");
|
||||||
|
String::Append(buffer, bufferSize, option->LongName);
|
||||||
|
|
||||||
|
switch (option->Type) {
|
||||||
|
case CMDLINE_TYPE_INTEGER:
|
||||||
|
String::Append(buffer, bufferSize, "=<int>");
|
||||||
|
break;
|
||||||
|
case CMDLINE_TYPE_REAL:
|
||||||
|
String::Append(buffer, bufferSize, "=<real>");
|
||||||
|
break;
|
||||||
|
case CMDLINE_TYPE_STRING:
|
||||||
|
String::Append(buffer, bufferSize, "=<str>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommandLineCommand * FindCommandFor(const CommandLineCommand * commands, const char * const * arguments, int count)
|
||||||
|
{
|
||||||
|
// Check if there are any arguments
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if options have started
|
||||||
|
const char * firstArgument = arguments[0];
|
||||||
|
if (firstArgument[0] == '-')
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search through defined commands for one that matches
|
||||||
|
const CommandLineCommand * fallback = nullptr;
|
||||||
|
const CommandLineCommand * command = commands;
|
||||||
|
for (; command->Name != nullptr; command++)
|
||||||
|
{
|
||||||
|
if (command->Name[0] == '\0')
|
||||||
|
{
|
||||||
|
// If we don't find a command, this should be used
|
||||||
|
fallback = command;
|
||||||
|
}
|
||||||
|
else if (String::Equals(command->Name, firstArgument))
|
||||||
|
{
|
||||||
|
if (command->SubCommands == nullptr)
|
||||||
|
{
|
||||||
|
// Found matching command
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Recurse for the sub command table
|
||||||
|
return FindCommandFor(command->SubCommands, &arguments[1], count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandLineDisplayUsageFor(const char * command)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
int cmdline_run(const char * * argv, int argc)
|
||||||
|
{
|
||||||
|
CommandLine::PrintHelp();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/cmdline/CommandLine.hpp
Normal file
83
src/cmdline/CommandLine.hpp
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "../common.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for enumerating and retrieving values for a set of command line arguments.
|
||||||
|
*/
|
||||||
|
class CommandLineArgEnumerator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const char * const * _arguments;
|
||||||
|
uint16 _count;
|
||||||
|
uint16 _index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint16 GetCount() const { return _count; }
|
||||||
|
uint16 GetIndex() const { return _index; }
|
||||||
|
|
||||||
|
CommandLineArgEnumerator(const char * const * arguments, int count);
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
bool TryPop();
|
||||||
|
bool TryPopInteger(sint32 * result);
|
||||||
|
bool TryPopReal(float * result);
|
||||||
|
bool TryPopString(const char * * result);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int exitcode_t;
|
||||||
|
typedef exitcode_t (*CommandLineFunc)(CommandLineArgEnumerator *);
|
||||||
|
|
||||||
|
struct CommandLineExample
|
||||||
|
{
|
||||||
|
const char * Arguments;
|
||||||
|
const char * Description;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommandLineOptionDefinition
|
||||||
|
{
|
||||||
|
uint8 Type;
|
||||||
|
void * OutAddress;
|
||||||
|
char ShortName;
|
||||||
|
const char * LongName;
|
||||||
|
const char * Description;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommandLineCommand
|
||||||
|
{
|
||||||
|
const char * Name;
|
||||||
|
const char * Parameters;
|
||||||
|
const CommandLineOptionDefinition * Options;
|
||||||
|
const CommandLineCommand * SubCommands;
|
||||||
|
CommandLineFunc Func;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CMDLINE_TYPE_SWITCH,
|
||||||
|
CMDLINE_TYPE_INTEGER,
|
||||||
|
CMDLINE_TYPE_REAL,
|
||||||
|
CMDLINE_TYPE_STRING,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr char NAC = '\0';
|
||||||
|
|
||||||
|
#define ExampleTableEnd { NULL, NULL }
|
||||||
|
#define OptionTableEnd { UINT8_MAX, NULL, NAC, NULL, NULL }
|
||||||
|
#define CommandTableEnd { NULL, NULL, NULL, NULL }
|
||||||
|
|
||||||
|
#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
|
||||||
|
{
|
||||||
|
void PrintHelp();
|
||||||
|
}
|
||||||
104
src/cmdline/CommandLineDefinitions.cpp
Normal file
104
src/cmdline/CommandLineDefinitions.cpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
32
src/core/Console.hpp
Normal file
32
src/core/Console.hpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "../common.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
80
src/core/String.hpp
Normal file
80
src/core/String.hpp
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../localisation/localisation.h"
|
||||||
|
#include "../util/util.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
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 * 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user