mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-08-04 03:07:07 -04:00
Refactor main loop somewhat
This commit is contained in:
parent
23aee471e5
commit
01c2e1c3fd
1
Makefile
1
Makefile
@ -61,6 +61,7 @@ ifeq ($(PLAT),web)
|
||||
CFLAGS = -g
|
||||
LDFLAGS = -g -s WASM=1 -s NO_EXIT_RUNTIME=1 -s ABORTING_MALLOC=0 -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=256Kb --js-library $(SOURCE_DIR)/interop_web.js
|
||||
BUILD_DIR = build/web
|
||||
BEARSSL = 0
|
||||
endif
|
||||
|
||||
ifeq ($(PLAT),mingw)
|
||||
|
30
src/Game.c
30
src/Game.c
@ -44,7 +44,7 @@
|
||||
|
||||
struct _GameData Game;
|
||||
static cc_uint64 frameStart;
|
||||
cc_bool Game_UseCPEBlocks;
|
||||
cc_bool Game_UseCPEBlocks, Game_Running;
|
||||
|
||||
struct RayTracer Game_SelectedPos;
|
||||
int Game_ViewDistance = DEFAULT_VIEWDIST;
|
||||
@ -53,7 +53,6 @@ int Game_MaxViewDistance = DEFAULT_MAX_VIEWDIST;
|
||||
|
||||
int Game_FpsLimit, Game_Vertices;
|
||||
cc_bool Game_SimpleArmsAnim;
|
||||
static cc_bool gameRunning;
|
||||
static float gfx_minFrameMs;
|
||||
static cc_bool autoPause;
|
||||
|
||||
@ -410,7 +409,7 @@ static void LoadPlugins(void) {
|
||||
static void LoadPlugins(void) { }
|
||||
#endif
|
||||
|
||||
static void Game_PendingClose(void* obj) { gameRunning = false; }
|
||||
static void Game_PendingClose(void* obj) { Game_Running = false; }
|
||||
static void Game_Load(void) {
|
||||
struct IGameComponent* comp;
|
||||
Game_UpdateDimensions();
|
||||
@ -844,8 +843,7 @@ static CC_INLINE void Game_RenderFrame(void) {
|
||||
if (gfx_minFrameMs) LimitFPS();
|
||||
}
|
||||
|
||||
|
||||
static void Game_Free(void) {
|
||||
void Game_Free(void) {
|
||||
struct IGameComponent* comp;
|
||||
/* Most components will call OnContextLost in their Free functions */
|
||||
/* Set to false so components will always free managed textures too */
|
||||
@ -858,7 +856,7 @@ static void Game_Free(void) {
|
||||
if (comp->Free) comp->Free();
|
||||
}
|
||||
|
||||
gameRunning = false;
|
||||
Game_Running = false;
|
||||
Logger_WarnFunc = Logger_DialogWarn;
|
||||
Gfx_Free();
|
||||
Options_SaveIfChanged();
|
||||
@ -867,7 +865,7 @@ static void Game_Free(void) {
|
||||
|
||||
#ifdef CC_BUILD_WEB
|
||||
void Game_DoFrame(void) {
|
||||
if (gameRunning) {
|
||||
if (Game_Running) {
|
||||
Game_RenderFrame();
|
||||
} else if (tasksCount) {
|
||||
Game_Free();
|
||||
@ -881,7 +879,7 @@ static void Game_RunLoop(void) {
|
||||
}
|
||||
|
||||
cc_bool Game_ShouldClose(void) {
|
||||
if (!gameRunning) return true;
|
||||
if (!Game_Running) return true;
|
||||
|
||||
if (Server.IsSinglePlayer) {
|
||||
/* Close if map was saved within last 5 seconds */
|
||||
@ -895,15 +893,15 @@ cc_bool Game_ShouldClose(void) {
|
||||
}
|
||||
#else
|
||||
static void Game_RunLoop(void) {
|
||||
while (gameRunning)
|
||||
while (Game_Running)
|
||||
{
|
||||
Game_RenderFrame();
|
||||
}
|
||||
Game_Free();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Game_Setup(const cc_string* title) {
|
||||
void Game_Setup(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);
|
||||
|
||||
@ -913,19 +911,21 @@ void Game_Setup(const cc_string* title) {
|
||||
if (DisplayInfo.Width < 854) width = 640;
|
||||
}
|
||||
|
||||
String_InitArray(title, titleBuffer);
|
||||
String_Format2(&title, "%c (%s)", GAME_APP_TITLE, &Game_Username);
|
||||
|
||||
Window_Create3D(width, height);
|
||||
Window_SetTitle(title);
|
||||
Window_SetTitle(&title);
|
||||
Window_Show();
|
||||
gameRunning = true;
|
||||
Game_Running = true;
|
||||
Game.CurrentState = 0;
|
||||
|
||||
Game_Load();
|
||||
Event_RaiseVoid(&WindowEvents.Resized);
|
||||
frameStart = Stopwatch_Measure();
|
||||
}
|
||||
|
||||
void Game_Run(void) {
|
||||
frameStart = Stopwatch_Measure();
|
||||
Game_RunLoop();
|
||||
Window_Destroy();
|
||||
}
|
||||
|
||||
|
10
src/Game.h
10
src/Game.h
@ -24,7 +24,7 @@ CC_VAR extern struct _GameData {
|
||||
} Game;
|
||||
|
||||
extern struct RayTracer Game_SelectedPos;
|
||||
extern cc_bool Game_UseCPEBlocks;
|
||||
extern cc_bool Game_UseCPEBlocks, Game_Running;
|
||||
|
||||
extern cc_string Game_Username;
|
||||
extern cc_string Game_Mppass;
|
||||
@ -124,10 +124,12 @@ cc_bool Game_ValidateBitmap(const cc_string* file, struct Bitmap* bmp);
|
||||
/* NOTE: Game_ValidateBitmap should nearly always be used instead of this */
|
||||
cc_bool Game_ValidateBitmapPow2(const cc_string* file, struct Bitmap* bmp);
|
||||
|
||||
/* Initialises and loads state, and creates the main window */
|
||||
void Game_Setup(const cc_string* title);
|
||||
/* Runs the main game loop until the window is closed. */
|
||||
/* Initialises and loads state, and creates the main game window */
|
||||
void Game_Setup(void);
|
||||
/* Runs the main game loop until the game loop is finished. */
|
||||
/* (e.g. by the user pressing Quit Game, or closing the game window) */
|
||||
void Game_Run(void);
|
||||
void Game_Free(void);
|
||||
/* Whether the game should be allowed to automatically close */
|
||||
cc_bool Game_ShouldClose(void);
|
||||
|
||||
|
@ -311,7 +311,6 @@ void Launcher_Finish(void) {
|
||||
cc_result res = Updater_Start(&action);
|
||||
if (res) Logger_SysWarn(res, action);
|
||||
}
|
||||
Window_Destroy();
|
||||
}
|
||||
|
||||
|
||||
|
@ -353,9 +353,8 @@ cc_bool Process_OpenSupported = true;
|
||||
|
||||
void Process_Exit(cc_result code) {
|
||||
/* 'Window' (i.e. the web canvas) isn't implicitly closed when process is exited */
|
||||
if (code) Window_RequestClose();
|
||||
/* game normally calls exit with code = 0 due to async IndexedDB loading */
|
||||
if (code) exit(code);
|
||||
Window_Free();
|
||||
exit(code);
|
||||
}
|
||||
|
||||
extern int interop_OpenTab(const char* url);
|
||||
@ -439,11 +438,20 @@ static char** _argv;
|
||||
/* webclient does some asynchronous initialisation first, then kickstarts the game after that */
|
||||
static void web_main(void) {
|
||||
SetupProgram(_argc, _argv);
|
||||
cc_result res = RunProgram(_argc, _argv);
|
||||
|
||||
if (!res) return;
|
||||
Window_Free();
|
||||
Process_Exit(res);
|
||||
switch (ProcessProgramArgs(_argc, _argv))
|
||||
{
|
||||
case ARG_RESULT_RUN_LAUNCHER:
|
||||
String_AppendConst(&Game_Username, DEFAULT_USERNAME);
|
||||
/* fallthrough */
|
||||
case ARG_RESULT_RUN_GAME:
|
||||
Game_Setup();
|
||||
Game_Run();
|
||||
return;
|
||||
|
||||
default:
|
||||
Process_Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -451,7 +459,7 @@ extern void interop_FS_Init(void);
|
||||
extern void interop_DirectorySetWorking(const char* path);
|
||||
extern void interop_AsyncDownloadTexturePack(const char* path);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
EMSCRIPTEN_KEEPALIVE int main(int argc, char** argv) {
|
||||
_argc = argc; _argv = argv;
|
||||
|
||||
/* Game loads resources asynchronously, then actually starts itself */
|
||||
|
107
src/main_impl.h
107
src/main_impl.h
@ -76,22 +76,18 @@ void DirectUrl_ExtractAddress(const cc_string* addr, cc_string* ip, cc_string* p
|
||||
*------------------------------------------------------Game setup/run-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void RunGame(void) {
|
||||
cc_string title; char titleBuffer[STRING_SIZE];
|
||||
String_InitArray(title, titleBuffer);
|
||||
|
||||
String_Format2(&title, "%c (%s)", GAME_APP_TITLE, &Game_Username);
|
||||
Game_Setup(&title);
|
||||
Game_Setup();
|
||||
Game_Run();
|
||||
Game_Free();
|
||||
Window_Destroy();
|
||||
}
|
||||
|
||||
static void RunLauncher(void) {
|
||||
#ifdef CC_BUILD_WEB
|
||||
String_AppendConst(&Game_Username, DEFAULT_USERNAME);
|
||||
RunGame();
|
||||
#else
|
||||
#ifndef CC_BUILD_WEB
|
||||
Launcher_Setup();
|
||||
Launcher_Run();
|
||||
Launcher_Finish();
|
||||
Window_Destroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -160,8 +156,12 @@ static int ParseMPArgs(const cc_string* user, const cc_string* mppass, const cc_
|
||||
return true;
|
||||
}
|
||||
|
||||
static int RunProgram(int argc, char** argv) {
|
||||
cc_string args[GAME_MAX_CMDARGS];
|
||||
#define ARG_RESULT_RUN_LAUNCHER 1
|
||||
#define ARG_RESULT_RUN_GAME 2
|
||||
#define ARG_RESULT_INVALID_ARGS 3
|
||||
|
||||
static int ProcessProgramArgs(int argc, char** argv) {
|
||||
cc_string args[GAME_MAX_CMDARGS];
|
||||
int argsCount = Platform_GetCommandLineArgs(argc, argv, args);
|
||||
struct ResumeInfo r;
|
||||
cc_string host;
|
||||
@ -173,52 +173,81 @@ static int RunProgram(int argc, char** argv) {
|
||||
//argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
|
||||
#endif
|
||||
|
||||
if (argsCount == 0) {
|
||||
RunLauncher();
|
||||
if (argsCount == 0)
|
||||
return ARG_RESULT_RUN_LAUNCHER;
|
||||
|
||||
#ifndef CC_BUILD_WEB
|
||||
/* :[hash] - auto join server with the given hash */
|
||||
} else if (argsCount == 1 && args[0].buffer[0] == ':') {
|
||||
if (argsCount == 1 && args[0].buffer[0] == ':') {
|
||||
args[0] = String_UNSAFE_SubstringAt(&args[0], 1);
|
||||
String_Copy(&Launcher_AutoHash, &args[0]);
|
||||
RunLauncher();
|
||||
return ARG_RESULT_RUN_LAUNCHER;
|
||||
}
|
||||
|
||||
/* --resume - try to resume to last server */
|
||||
} else if (argsCount == 1 && String_CaselessEqualsConst(&args[0], DEFAULT_RESUME_ARG)) {
|
||||
if (argsCount == 1 && String_CaselessEqualsConst(&args[0], DEFAULT_RESUME_ARG)) {
|
||||
if (!Resume_Parse(&r, true)) {
|
||||
WarnInvalidArg("No server to resume to", &args[0]);
|
||||
return 1;
|
||||
return ARG_RESULT_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port)) return 1;
|
||||
RunGame();
|
||||
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port))
|
||||
return ARG_RESULT_INVALID_ARGS;
|
||||
return ARG_RESULT_RUN_GAME;
|
||||
}
|
||||
|
||||
/* --singleplayer' - run singleplayer with default user */
|
||||
} else if (argsCount == 1 && String_CaselessEqualsConst(&args[0], DEFAULT_SINGLEPLAYER_ARG)) {
|
||||
if (argsCount == 1 && String_CaselessEqualsConst(&args[0], DEFAULT_SINGLEPLAYER_ARG)) {
|
||||
Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME);
|
||||
RunGame();
|
||||
return ARG_RESULT_RUN_GAME;
|
||||
}
|
||||
|
||||
/* [file path] - run singleplayer with auto loaded map */
|
||||
} else if (argsCount == 1 && IsOpenableFile(&args[0])) {
|
||||
if (argsCount == 1 && IsOpenableFile(&args[0])) {
|
||||
Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME);
|
||||
String_Copy(&SP_AutoloadMap, &args[0]); /* TODO: don't copy args? */
|
||||
RunGame();
|
||||
return ARG_RESULT_RUN_GAME;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* mc://[addr]:[port]/[user]/[mppass] - run multiplayer using direct URL form arguments */
|
||||
} else if (argsCount == 1 && DirectUrl_Claims(&args[0], &host, &r.user, &r.mppass)) {
|
||||
if (argsCount == 1 && DirectUrl_Claims(&args[0], &host, &r.user, &r.mppass)) {
|
||||
DirectUrl_ExtractAddress(&host, &r.ip, &r.port);
|
||||
|
||||
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port)) return 1;
|
||||
RunGame();
|
||||
/* [user] - run multiplayer using explicit username */
|
||||
} else if (argsCount == 1) {
|
||||
String_Copy(&Game_Username, &args[0]);
|
||||
RunGame();
|
||||
/* 2 to 3 arguments - unsupported at present */
|
||||
} else if (argsCount < 4) {
|
||||
WarnMissingArgs(argsCount, args);
|
||||
return 1;
|
||||
/* [user] [mppass] [address] [port] - run multiplayer using explicit arguments */
|
||||
} else {
|
||||
if (!ParseMPArgs(&args[0], &args[1], &args[2], &args[3])) return 1;
|
||||
RunGame();
|
||||
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port))
|
||||
return ARG_RESULT_INVALID_ARGS;
|
||||
return ARG_RESULT_RUN_GAME;
|
||||
}
|
||||
|
||||
/* [user] - run multiplayer using explicit username */
|
||||
if (argsCount == 1) {
|
||||
String_Copy(&Game_Username, &args[0]);
|
||||
return ARG_RESULT_RUN_GAME;
|
||||
}
|
||||
|
||||
/* 2 to 3 arguments - unsupported at present */
|
||||
if (argsCount < 4) {
|
||||
WarnMissingArgs(argsCount, args);
|
||||
return ARG_RESULT_INVALID_ARGS;
|
||||
}
|
||||
|
||||
/* [user] [mppass] [address] [port] - run multiplayer using explicit arguments */
|
||||
if (!ParseMPArgs(&args[0], &args[1], &args[2], &args[3]))
|
||||
return ARG_RESULT_INVALID_ARGS;
|
||||
return ARG_RESULT_RUN_GAME;
|
||||
}
|
||||
|
||||
static int RunProgram(int argc, char** argv) {
|
||||
switch (ProcessProgramArgs(argc, argv))
|
||||
{
|
||||
case ARG_RESULT_RUN_LAUNCHER:
|
||||
RunLauncher();
|
||||
return 0;
|
||||
case ARG_RESULT_RUN_GAME:
|
||||
RunGame();
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ static void ProcessCircleInput(int port, int axis, int x, int y, float delta) {
|
||||
}
|
||||
|
||||
static void ProcessPadInput(float delta) {
|
||||
int port = Gamepad_Connect(0x503, PadBind_Defaults);
|
||||
int port = Gamepad_Connect(0x503, vita_padbinds);
|
||||
SceCtrlData pad;
|
||||
|
||||
// sceCtrlReadBufferPositive is blocking (seems to block until vblank), and don't want that
|
||||
|
Loading…
x
Reference in New Issue
Block a user