diff options
author | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
---|---|---|
committer | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
commit | abef6da56913f1c55528103e60a50451a39628b1 (patch) | |
tree | b3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/main.c |
initial commit
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..02ea2c0 --- /dev/null +++ b/src/main.c @@ -0,0 +1,177 @@ +#include "Logger.h" +#include "String.h" +#include "Platform.h" +#include "Window.h" +#include "Constants.h" +#include "Game.h" +#include "Funcs.h" +#include "Utils.h" +#include "Launcher.h" +#include "Server.h" +#include "Options.h" + +static void RunGame(void) { + cc_string title; char titleBuffer[STRING_SIZE]; + int width = Options_GetInt(OPT_WINDOW_WIDTH, 0, DisplayInfo.Width, 0); + int height = Options_GetInt(OPT_WINDOW_HEIGHT, 0, DisplayInfo.Height, 0); + + /* No custom resolution has been set */ + if (width == 0 || height == 0) { + width = 854; height = 480; + if (DisplayInfo.Width < 854) width = 640; + } + + String_InitArray(title, titleBuffer); + String_Format2(&title, "%c (%s)", GAME_APP_TITLE, &Game_Username); + Game_Run(width, height, &title); +} + +/* Shows a warning dialog due to an invalid command line argument */ +CC_NOINLINE static void WarnInvalidArg(const char* name, const cc_string* arg) { + cc_string tmp; char tmpBuffer[256]; + String_InitArray(tmp, tmpBuffer); + String_Format2(&tmp, "%c '%s'", name, arg); + + Logger_DialogTitle = "Failed to start"; + Logger_DialogWarn(&tmp); +} + +/* Shows a warning dialog due to insufficient command line arguments */ +CC_NOINLINE static void WarnMissingArgs(int argsCount, const cc_string* args) { + cc_string tmp; char tmpBuffer[256]; + int i; + String_InitArray(tmp, tmpBuffer); + + String_AppendConst(&tmp, "Missing IP and/or port - "); + for (i = 0; i < argsCount; i++) { + String_AppendString(&tmp, &args[i]); + String_Append(&tmp, ' '); + } + + Logger_DialogTitle = "Failed to start"; + Logger_DialogWarn(&tmp); +} + +static void SetupProgram(int argc, char** argv) { + static char ipBuffer[STRING_SIZE]; + cc_result res; + Logger_Hook(); + Window_PreInit(); + Platform_Init(); + + res = Platform_SetDefaultCurrentDirectory(argc, argv); + Options_Load(); + Window_Init(); + + if (res) Logger_SysWarn(res, "setting current directory"); + Platform_LogConst("Starting " GAME_APP_NAME " .."); + String_InitArray(Server.Address, ipBuffer); +} + +#define SP_HasDir(path) (String_IndexOf(&path, '/') >= 0 || String_IndexOf(&path, '\\') >= 0) + +static int RunProgram(int argc, char** argv) { + cc_string args[GAME_MAX_CMDARGS]; + cc_uint16 port; + + int argsCount = Platform_GetCommandLineArgs(argc, argv, args); +#ifdef _MSC_VER + /* NOTE: Make sure to comment this out before pushing a commit */ + //cc_string rawArgs = String_FromConst("UnknownShadow200 fffff 127.0.0.1 25565"); + //cc_string rawArgs = String_FromConst("UnknownShadow200"); + //argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4); +#endif + + if (argsCount == 0) { +#ifdef CC_BUILD_WEB + String_AppendConst(&Game_Username, DEFAULT_USERNAME); + RunGame(); +#else + Launcher_Run(); + /* :hash to auto join server with the given hash */ + } else if (argsCount == 1 && args[0].buffer[0] == ':') { + args[0] = String_UNSAFE_SubstringAt(&args[0], 1); + String_Copy(&Launcher_AutoHash, &args[0]); + Launcher_Run(); + /* File path to auto load a map in singleplayer */ + } else if (argsCount == 1 && SP_HasDir(args[0]) && File_Exists(&args[0])) { + Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME); + String_Copy(&SP_AutoloadMap, &args[0]); /* TODO: don't copy args? */ + RunGame(); +#endif + } else if (argsCount == 1) { + String_Copy(&Game_Username, &args[0]); + RunGame(); + } else if (argsCount < 4) { + WarnMissingArgs(argsCount, args); + return 1; + } else { + String_Copy(&Game_Username, &args[0]); + String_Copy(&Game_Mppass, &args[1]); + String_Copy(&Server.Address,&args[2]); + + if (!Convert_ParseUInt16(&args[3], &port)) { + WarnInvalidArg("Invalid port", &args[3]); + return 1; + } + Server.Port = port; + RunGame(); + } + return 0; +} + +#if defined CC_BUILD_IOS +/* ClassiCube is sort of and sort of not the executable */ +/* on iOS - UIKit is responsible for kickstarting the game. */ +/* (this is handled in interop_ios.m as the code is Objective C) */ +int ios_main(int argc, char** argv) { + SetupProgram(argc, argv); + for (;;) { RunProgram(argc, argv); } + return 0; +} +#elif defined CC_BUILD_ANDROID +/* ClassiCube is just a native library on android, */ +/* unlike other platforms where it is the executable. */ +/* (activity java class is responsible for kickstarting the game, + see Platform_Android.c for the code that actually calls this) */ +void android_main(void) { + Platform_LogConst("Main loop started!"); + SetupProgram(0, NULL); + for (;;) { RunProgram(0, NULL); } +} +#elif defined CC_BUILD_CONSOLE +int main(int argc, char** argv) { + SetupProgram(argc, argv); + while (Window_Main.Exists) { + RunProgram(argc, argv); + } + + Window_Free(); + return 0; +} +#else +/* NOTE: main_real is used for when compiling with MinGW without linking to startup files. */ +/* Normally, the final code produced for "main" is our "main" combined with crt's main */ +/* (mingw-w64-crt/crt/gccmain.c) - alas this immediately crashes the game on startup. */ +/* Using main_real instead and setting main_real as the entrypoint fixes the crash. */ +#if defined CC_NOMAIN +int main_real(int argc, char** argv) { +#elif defined CC_BUILD_WEB +/* webclient does some asynchronous initialisation first, then kickstarts the game after that */ +int web_main(int argc, char** argv) { +#else +int main(int argc, char** argv) { +#endif + cc_result res; + SetupProgram(argc, argv); + + /* If single process mode, then the loop is launcher -> game -> launcher etc */ + do { + res = RunProgram(argc, argv); + } while (Platform_SingleProcess && Window_Main.Exists); + + Window_Free(); + Process_Exit(res); + return res; +} +#endif |