summary refs log tree commit diff
path: root/src/main.c
diff options
context:
space:
mode:
authorWlodekM <[email protected]>2024-06-16 10:35:45 +0300
committerWlodekM <[email protected]>2024-06-16 10:35:45 +0300
commitabef6da56913f1c55528103e60a50451a39628b1 (patch)
treeb3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/main.c
initial commit
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c177
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