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
|
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
|
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
|
BUILD_DIR = build/web
|
||||||
|
BEARSSL = 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(PLAT),mingw)
|
ifeq ($(PLAT),mingw)
|
||||||
|
30
src/Game.c
30
src/Game.c
@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
struct _GameData Game;
|
struct _GameData Game;
|
||||||
static cc_uint64 frameStart;
|
static cc_uint64 frameStart;
|
||||||
cc_bool Game_UseCPEBlocks;
|
cc_bool Game_UseCPEBlocks, Game_Running;
|
||||||
|
|
||||||
struct RayTracer Game_SelectedPos;
|
struct RayTracer Game_SelectedPos;
|
||||||
int Game_ViewDistance = DEFAULT_VIEWDIST;
|
int Game_ViewDistance = DEFAULT_VIEWDIST;
|
||||||
@ -53,7 +53,6 @@ int Game_MaxViewDistance = DEFAULT_MAX_VIEWDIST;
|
|||||||
|
|
||||||
int Game_FpsLimit, Game_Vertices;
|
int Game_FpsLimit, Game_Vertices;
|
||||||
cc_bool Game_SimpleArmsAnim;
|
cc_bool Game_SimpleArmsAnim;
|
||||||
static cc_bool gameRunning;
|
|
||||||
static float gfx_minFrameMs;
|
static float gfx_minFrameMs;
|
||||||
static cc_bool autoPause;
|
static cc_bool autoPause;
|
||||||
|
|
||||||
@ -410,7 +409,7 @@ static void LoadPlugins(void) {
|
|||||||
static void LoadPlugins(void) { }
|
static void LoadPlugins(void) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void Game_PendingClose(void* obj) { gameRunning = false; }
|
static void Game_PendingClose(void* obj) { Game_Running = false; }
|
||||||
static void Game_Load(void) {
|
static void Game_Load(void) {
|
||||||
struct IGameComponent* comp;
|
struct IGameComponent* comp;
|
||||||
Game_UpdateDimensions();
|
Game_UpdateDimensions();
|
||||||
@ -844,8 +843,7 @@ static CC_INLINE void Game_RenderFrame(void) {
|
|||||||
if (gfx_minFrameMs) LimitFPS();
|
if (gfx_minFrameMs) LimitFPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Game_Free(void) {
|
||||||
static void Game_Free(void) {
|
|
||||||
struct IGameComponent* comp;
|
struct IGameComponent* comp;
|
||||||
/* Most components will call OnContextLost in their Free functions */
|
/* Most components will call OnContextLost in their Free functions */
|
||||||
/* Set to false so components will always free managed textures too */
|
/* 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();
|
if (comp->Free) comp->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
gameRunning = false;
|
Game_Running = false;
|
||||||
Logger_WarnFunc = Logger_DialogWarn;
|
Logger_WarnFunc = Logger_DialogWarn;
|
||||||
Gfx_Free();
|
Gfx_Free();
|
||||||
Options_SaveIfChanged();
|
Options_SaveIfChanged();
|
||||||
@ -867,7 +865,7 @@ static void Game_Free(void) {
|
|||||||
|
|
||||||
#ifdef CC_BUILD_WEB
|
#ifdef CC_BUILD_WEB
|
||||||
void Game_DoFrame(void) {
|
void Game_DoFrame(void) {
|
||||||
if (gameRunning) {
|
if (Game_Running) {
|
||||||
Game_RenderFrame();
|
Game_RenderFrame();
|
||||||
} else if (tasksCount) {
|
} else if (tasksCount) {
|
||||||
Game_Free();
|
Game_Free();
|
||||||
@ -881,7 +879,7 @@ static void Game_RunLoop(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cc_bool Game_ShouldClose(void) {
|
cc_bool Game_ShouldClose(void) {
|
||||||
if (!gameRunning) return true;
|
if (!Game_Running) return true;
|
||||||
|
|
||||||
if (Server.IsSinglePlayer) {
|
if (Server.IsSinglePlayer) {
|
||||||
/* Close if map was saved within last 5 seconds */
|
/* Close if map was saved within last 5 seconds */
|
||||||
@ -895,15 +893,15 @@ cc_bool Game_ShouldClose(void) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void Game_RunLoop(void) {
|
static void Game_RunLoop(void) {
|
||||||
while (gameRunning)
|
while (Game_Running)
|
||||||
{
|
{
|
||||||
Game_RenderFrame();
|
Game_RenderFrame();
|
||||||
}
|
}
|
||||||
Game_Free();
|
|
||||||
}
|
}
|
||||||
#endif
|
#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 width = Options_GetInt(OPT_WINDOW_WIDTH, 0, DisplayInfo.Width, 0);
|
||||||
int height = Options_GetInt(OPT_WINDOW_HEIGHT, 0, DisplayInfo.Height, 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;
|
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_Create3D(width, height);
|
||||||
Window_SetTitle(title);
|
Window_SetTitle(&title);
|
||||||
Window_Show();
|
Window_Show();
|
||||||
gameRunning = true;
|
Game_Running = true;
|
||||||
Game.CurrentState = 0;
|
Game.CurrentState = 0;
|
||||||
|
|
||||||
Game_Load();
|
Game_Load();
|
||||||
Event_RaiseVoid(&WindowEvents.Resized);
|
Event_RaiseVoid(&WindowEvents.Resized);
|
||||||
|
frameStart = Stopwatch_Measure();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game_Run(void) {
|
void Game_Run(void) {
|
||||||
frameStart = Stopwatch_Measure();
|
|
||||||
Game_RunLoop();
|
Game_RunLoop();
|
||||||
Window_Destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/Game.h
10
src/Game.h
@ -24,7 +24,7 @@ CC_VAR extern struct _GameData {
|
|||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
extern struct RayTracer Game_SelectedPos;
|
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_Username;
|
||||||
extern cc_string Game_Mppass;
|
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 */
|
/* NOTE: Game_ValidateBitmap should nearly always be used instead of this */
|
||||||
cc_bool Game_ValidateBitmapPow2(const cc_string* file, struct Bitmap* bmp);
|
cc_bool Game_ValidateBitmapPow2(const cc_string* file, struct Bitmap* bmp);
|
||||||
|
|
||||||
/* Initialises and loads state, and creates the main window */
|
/* Initialises and loads state, and creates the main game window */
|
||||||
void Game_Setup(const cc_string* title);
|
void Game_Setup(void);
|
||||||
/* Runs the main game loop until the window is closed. */
|
/* 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_Run(void);
|
||||||
|
void Game_Free(void);
|
||||||
/* Whether the game should be allowed to automatically close */
|
/* Whether the game should be allowed to automatically close */
|
||||||
cc_bool Game_ShouldClose(void);
|
cc_bool Game_ShouldClose(void);
|
||||||
|
|
||||||
|
@ -311,7 +311,6 @@ void Launcher_Finish(void) {
|
|||||||
cc_result res = Updater_Start(&action);
|
cc_result res = Updater_Start(&action);
|
||||||
if (res) Logger_SysWarn(res, action);
|
if (res) Logger_SysWarn(res, action);
|
||||||
}
|
}
|
||||||
Window_Destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -353,9 +353,8 @@ cc_bool Process_OpenSupported = true;
|
|||||||
|
|
||||||
void Process_Exit(cc_result code) {
|
void Process_Exit(cc_result code) {
|
||||||
/* 'Window' (i.e. the web canvas) isn't implicitly closed when process is exited */
|
/* 'Window' (i.e. the web canvas) isn't implicitly closed when process is exited */
|
||||||
if (code) Window_RequestClose();
|
Window_Free();
|
||||||
/* game normally calls exit with code = 0 due to async IndexedDB loading */
|
exit(code);
|
||||||
if (code) exit(code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int interop_OpenTab(const char* url);
|
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 */
|
/* webclient does some asynchronous initialisation first, then kickstarts the game after that */
|
||||||
static void web_main(void) {
|
static void web_main(void) {
|
||||||
SetupProgram(_argc, _argv);
|
SetupProgram(_argc, _argv);
|
||||||
cc_result res = RunProgram(_argc, _argv);
|
|
||||||
|
|
||||||
if (!res) return;
|
switch (ProcessProgramArgs(_argc, _argv))
|
||||||
Window_Free();
|
{
|
||||||
Process_Exit(res);
|
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_DirectorySetWorking(const char* path);
|
||||||
extern void interop_AsyncDownloadTexturePack(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;
|
_argc = argc; _argv = argv;
|
||||||
|
|
||||||
/* Game loads resources asynchronously, then actually starts itself */
|
/* 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-----------------------------------------------------*
|
*------------------------------------------------------Game setup/run-----------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
static void RunGame(void) {
|
static void RunGame(void) {
|
||||||
cc_string title; char titleBuffer[STRING_SIZE];
|
Game_Setup();
|
||||||
String_InitArray(title, titleBuffer);
|
|
||||||
|
|
||||||
String_Format2(&title, "%c (%s)", GAME_APP_TITLE, &Game_Username);
|
|
||||||
Game_Setup(&title);
|
|
||||||
Game_Run();
|
Game_Run();
|
||||||
|
Game_Free();
|
||||||
|
Window_Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RunLauncher(void) {
|
static void RunLauncher(void) {
|
||||||
#ifdef CC_BUILD_WEB
|
#ifndef CC_BUILD_WEB
|
||||||
String_AppendConst(&Game_Username, DEFAULT_USERNAME);
|
|
||||||
RunGame();
|
|
||||||
#else
|
|
||||||
Launcher_Setup();
|
Launcher_Setup();
|
||||||
Launcher_Run();
|
Launcher_Run();
|
||||||
Launcher_Finish();
|
Launcher_Finish();
|
||||||
|
Window_Destroy();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,8 +156,12 @@ static int ParseMPArgs(const cc_string* user, const cc_string* mppass, const cc_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int RunProgram(int argc, char** argv) {
|
#define ARG_RESULT_RUN_LAUNCHER 1
|
||||||
cc_string args[GAME_MAX_CMDARGS];
|
#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);
|
int argsCount = Platform_GetCommandLineArgs(argc, argv, args);
|
||||||
struct ResumeInfo r;
|
struct ResumeInfo r;
|
||||||
cc_string host;
|
cc_string host;
|
||||||
@ -173,52 +173,81 @@ static int RunProgram(int argc, char** argv) {
|
|||||||
//argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
|
//argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (argsCount == 0) {
|
if (argsCount == 0)
|
||||||
RunLauncher();
|
return ARG_RESULT_RUN_LAUNCHER;
|
||||||
|
|
||||||
#ifndef CC_BUILD_WEB
|
#ifndef CC_BUILD_WEB
|
||||||
/* :[hash] - auto join server with the given hash */
|
/* :[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);
|
args[0] = String_UNSAFE_SubstringAt(&args[0], 1);
|
||||||
String_Copy(&Launcher_AutoHash, &args[0]);
|
String_Copy(&Launcher_AutoHash, &args[0]);
|
||||||
RunLauncher();
|
return ARG_RESULT_RUN_LAUNCHER;
|
||||||
|
}
|
||||||
|
|
||||||
/* --resume - try to resume to last server */
|
/* --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)) {
|
if (!Resume_Parse(&r, true)) {
|
||||||
WarnInvalidArg("No server to resume to", &args[0]);
|
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;
|
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port))
|
||||||
RunGame();
|
return ARG_RESULT_INVALID_ARGS;
|
||||||
|
return ARG_RESULT_RUN_GAME;
|
||||||
|
}
|
||||||
|
|
||||||
/* --singleplayer' - run singleplayer with default user */
|
/* --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);
|
Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME);
|
||||||
RunGame();
|
return ARG_RESULT_RUN_GAME;
|
||||||
|
}
|
||||||
|
|
||||||
/* [file path] - run singleplayer with auto loaded map */
|
/* [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);
|
Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME);
|
||||||
String_Copy(&SP_AutoloadMap, &args[0]); /* TODO: don't copy args? */
|
String_Copy(&SP_AutoloadMap, &args[0]); /* TODO: don't copy args? */
|
||||||
RunGame();
|
return ARG_RESULT_RUN_GAME;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* mc://[addr]:[port]/[user]/[mppass] - run multiplayer using direct URL form arguments */
|
/* 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);
|
DirectUrl_ExtractAddress(&host, &r.ip, &r.port);
|
||||||
|
|
||||||
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port)) return 1;
|
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port))
|
||||||
RunGame();
|
return ARG_RESULT_INVALID_ARGS;
|
||||||
/* [user] - run multiplayer using explicit username */
|
return ARG_RESULT_RUN_GAME;
|
||||||
} else if (argsCount == 1) {
|
}
|
||||||
String_Copy(&Game_Username, &args[0]);
|
|
||||||
RunGame();
|
/* [user] - run multiplayer using explicit username */
|
||||||
/* 2 to 3 arguments - unsupported at present */
|
if (argsCount == 1) {
|
||||||
} else if (argsCount < 4) {
|
String_Copy(&Game_Username, &args[0]);
|
||||||
WarnMissingArgs(argsCount, args);
|
return ARG_RESULT_RUN_GAME;
|
||||||
return 1;
|
}
|
||||||
/* [user] [mppass] [address] [port] - run multiplayer using explicit arguments */
|
|
||||||
} else {
|
/* 2 to 3 arguments - unsupported at present */
|
||||||
if (!ParseMPArgs(&args[0], &args[1], &args[2], &args[3])) return 1;
|
if (argsCount < 4) {
|
||||||
RunGame();
|
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) {
|
static void ProcessPadInput(float delta) {
|
||||||
int port = Gamepad_Connect(0x503, PadBind_Defaults);
|
int port = Gamepad_Connect(0x503, vita_padbinds);
|
||||||
SceCtrlData pad;
|
SceCtrlData pad;
|
||||||
|
|
||||||
// sceCtrlReadBufferPositive is blocking (seems to block until vblank), and don't want that
|
// sceCtrlReadBufferPositive is blocking (seems to block until vblank), and don't want that
|
||||||
|
Loading…
x
Reference in New Issue
Block a user