2026-01-12 01:54:35 +09:00
|
|
|
#include <GearSrc/Core.h>
|
2026-01-09 00:40:51 +09:00
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
#include <GearSrc/Version.h>
|
|
|
|
|
#include <GearSrc/Log.h>
|
|
|
|
|
#include <GearSrc/Client.h>
|
|
|
|
|
#include <GearSrc/Server.h>
|
|
|
|
|
#include <GearSrc/Resource.h>
|
2026-01-12 07:28:24 +09:00
|
|
|
#include <GearSrc/String.h>
|
2026-01-10 00:55:45 +09:00
|
|
|
|
|
|
|
|
#include <stb_ds.h>
|
2026-01-09 03:38:29 +09:00
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
void GSInit(void) {
|
|
|
|
|
GSVersion version;
|
2026-01-09 00:40:51 +09:00
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
GSVersionGet(&version);
|
2026-01-09 00:40:51 +09:00
|
|
|
|
2026-01-25 13:35:09 +09:00
|
|
|
GSLog(NULL, GSLogInfo, "GearSrc Engine %s", version.string);
|
2026-01-09 00:40:51 +09:00
|
|
|
}
|
|
|
|
|
|
2026-01-20 14:07:56 +09:00
|
|
|
GSBool GSEngineRegisterResource(GSEngine engine, const char* name, const char* path) {
|
2026-01-12 01:54:35 +09:00
|
|
|
GSResource resource;
|
|
|
|
|
if((resource = GSResourceOpen(engine, path)) != NULL) {
|
2026-01-10 18:23:33 +09:00
|
|
|
shput(engine->resource, name, resource);
|
|
|
|
|
|
2026-01-25 13:35:09 +09:00
|
|
|
GSLog(engine, GSLogInfo, "Registered resource %s as %s", path, name);
|
2026-01-13 04:28:36 +09:00
|
|
|
|
2026-01-20 14:07:56 +09:00
|
|
|
return GSTrue;
|
2026-01-10 18:23:33 +09:00
|
|
|
}
|
|
|
|
|
|
2026-01-20 14:07:56 +09:00
|
|
|
return GSFalse;
|
2026-01-10 18:23:33 +09:00
|
|
|
}
|
|
|
|
|
|
2026-01-13 04:28:36 +09:00
|
|
|
void GSEngineUnregisterResource(GSEngine engine, const char* name) {
|
|
|
|
|
int ind = shgeti(engine->resource, name);
|
|
|
|
|
|
|
|
|
|
if(ind != -1) {
|
|
|
|
|
GSResourceClose(engine->resource[ind].value);
|
|
|
|
|
|
2026-01-25 13:35:09 +09:00
|
|
|
GSLog(engine, GSLogInfo, "Unregistered resource %s", name);
|
2026-01-13 04:28:36 +09:00
|
|
|
|
|
|
|
|
shdel(engine->resource, name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
GSEngine GSEngineCreate(GSEngineParam* param) {
|
|
|
|
|
GSEngine engine = malloc(sizeof(*engine));
|
2026-01-09 00:40:51 +09:00
|
|
|
|
|
|
|
|
memset(engine, 0, sizeof(*engine));
|
|
|
|
|
|
2026-01-09 03:38:29 +09:00
|
|
|
engine->param = malloc(sizeof(*engine->param));
|
|
|
|
|
memcpy(engine->param, param, sizeof(*param));
|
|
|
|
|
|
2026-01-27 12:10:08 +09:00
|
|
|
engine->width = 800;
|
|
|
|
|
engine->height = 600;
|
|
|
|
|
engine->shutdown = 0;
|
2026-01-11 01:36:32 +09:00
|
|
|
|
|
|
|
|
if(param->ready != NULL && param->client) {
|
|
|
|
|
param->ready(engine->width, engine->height);
|
2026-01-09 03:38:29 +09:00
|
|
|
}
|
|
|
|
|
|
2026-01-12 06:15:07 +09:00
|
|
|
gload_init();
|
|
|
|
|
|
2026-01-10 00:55:45 +09:00
|
|
|
sh_new_strdup(engine->resource);
|
|
|
|
|
|
2026-01-19 07:06:52 +09:00
|
|
|
GSEngineRegisterResource(engine, "base", "base.gsp");
|
|
|
|
|
GSEngineRegisterResource(engine, "game", "game.gsp");
|
2026-01-10 00:55:45 +09:00
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
if(engine != NULL && param->client && (engine->client = GSClientCreate(engine)) == NULL) {
|
2026-01-25 13:35:09 +09:00
|
|
|
GSLog(engine, GSLogError, "Failed to create client");
|
2026-01-09 00:40:51 +09:00
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
GSEngineDestroy(engine);
|
2026-01-09 00:40:51 +09:00
|
|
|
|
|
|
|
|
engine = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
if(engine != NULL && param->server && (engine->server = GSServerCreate(engine)) == NULL) {
|
2026-01-25 13:35:09 +09:00
|
|
|
GSLog(engine, GSLogError, "Failed to create server");
|
2026-01-09 00:40:51 +09:00
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
GSEngineDestroy(engine);
|
2026-01-09 00:40:51 +09:00
|
|
|
|
|
|
|
|
engine = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-27 12:10:08 +09:00
|
|
|
if(param->client) engine->shutdown++;
|
|
|
|
|
if(param->server) engine->shutdown++;
|
|
|
|
|
|
2026-01-09 00:40:51 +09:00
|
|
|
if(engine == NULL) {
|
2026-01-25 13:35:09 +09:00
|
|
|
GSLog(engine, GSLogError, "Failed to create engine");
|
2026-01-09 00:40:51 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return engine;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
void GSEngineDestroy(GSEngine engine) {
|
2026-01-10 01:59:34 +09:00
|
|
|
int i;
|
|
|
|
|
for(i = 0; i < shlen(engine->resource); i++) {
|
2026-01-12 01:54:35 +09:00
|
|
|
GSResourceClose(engine->resource[i].value);
|
2026-01-10 01:59:34 +09:00
|
|
|
}
|
2026-01-10 00:55:45 +09:00
|
|
|
shfree(engine->resource);
|
|
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
if(engine->server != NULL) GSServerDestroy(engine->server);
|
|
|
|
|
if(engine->client != NULL) GSClientDestroy(engine->client);
|
2026-01-09 03:38:29 +09:00
|
|
|
if(engine->param != NULL) free(engine->param);
|
2026-01-09 00:40:51 +09:00
|
|
|
|
|
|
|
|
free(engine);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
void GSEngineParamInit(GSEngineParam* param) {
|
2026-01-09 03:38:29 +09:00
|
|
|
memset(param, 0, sizeof(*param));
|
|
|
|
|
|
2026-01-09 06:12:57 +09:00
|
|
|
param->server = 0;
|
|
|
|
|
param->client = 1;
|
|
|
|
|
param->gl_swapbuffer = NULL;
|
|
|
|
|
param->ready = NULL;
|
|
|
|
|
param->sleep = NULL;
|
|
|
|
|
param->get_tick = NULL;
|
2026-01-09 00:40:51 +09:00
|
|
|
}
|
|
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
void GSEngineLoop(GSEngine engine) {
|
2026-01-25 01:56:36 +09:00
|
|
|
long t = 0;
|
|
|
|
|
int wait_actually = 0;
|
|
|
|
|
GSNumber tps = 50;
|
2026-01-25 06:31:19 +09:00
|
|
|
GSNumber tick = 1;
|
|
|
|
|
int f = 5;
|
2026-01-25 01:56:36 +09:00
|
|
|
long wait = 1000 / tps;
|
2026-01-09 03:38:29 +09:00
|
|
|
|
|
|
|
|
if(engine->param->sleep == NULL || engine->param->get_tick == NULL) {
|
2026-01-25 13:35:09 +09:00
|
|
|
GSLog(engine, GSLogWarn, "sleep and/or get_tick parameter are missing!");
|
|
|
|
|
GSLog(engine, GSLogWarn, "This will result game to be crazy fast!!!");
|
2026-01-09 03:38:29 +09:00
|
|
|
} else {
|
|
|
|
|
t = engine->param->get_tick();
|
|
|
|
|
|
|
|
|
|
wait_actually = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-25 06:31:19 +09:00
|
|
|
engine->tps = tps;
|
|
|
|
|
engine->tps_sampled = tps;
|
2026-01-25 01:56:36 +09:00
|
|
|
|
2026-01-27 12:10:08 +09:00
|
|
|
while(engine->shutdown > 0) {
|
2026-01-12 01:54:35 +09:00
|
|
|
if(engine->client != NULL) GSClientStep(engine->client);
|
|
|
|
|
if(engine->server != NULL) GSServerStep(engine->server);
|
2026-01-09 03:38:29 +09:00
|
|
|
|
|
|
|
|
if(engine->param->tick != NULL) engine->param->tick();
|
|
|
|
|
|
2026-01-25 01:56:36 +09:00
|
|
|
if(wait_actually) {
|
|
|
|
|
if(!engine->param->client) {
|
|
|
|
|
int diff = (engine->param->get_tick() - t);
|
|
|
|
|
|
|
|
|
|
if(wait > diff)
|
|
|
|
|
engine->param->sleep(wait - diff);
|
|
|
|
|
}
|
2026-01-09 03:38:29 +09:00
|
|
|
|
2026-01-25 01:56:36 +09:00
|
|
|
engine->tps = 1000.0 / (engine->param->get_tick() - t);
|
2026-01-12 17:39:21 +09:00
|
|
|
|
2026-01-25 06:31:19 +09:00
|
|
|
if(f > 0) {
|
|
|
|
|
engine->tps_sampled = engine->tps;
|
|
|
|
|
|
|
|
|
|
f--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tick += 1.0 / engine->tps;
|
|
|
|
|
if(tick >= 1) {
|
|
|
|
|
engine->tps_sampled += engine->tps;
|
|
|
|
|
engine->tps_sampled /= 2;
|
|
|
|
|
|
|
|
|
|
tick = tick - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 03:38:29 +09:00
|
|
|
t = engine->param->get_tick();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
GSClient GSEngineGetClient(GSEngine engine) {
|
2026-01-09 03:38:29 +09:00
|
|
|
return engine->client;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-12 01:54:35 +09:00
|
|
|
GSServer GSEngineGetServer(GSEngine engine) {
|
2026-01-09 03:38:29 +09:00
|
|
|
return engine->server;
|
2026-01-09 00:40:51 +09:00
|
|
|
}
|
2026-01-25 13:05:30 +09:00
|
|
|
|
|
|
|
|
GSNumber GSEngineGetTPS(GSEngine engine) {
|
|
|
|
|
return engine->tps;
|
|
|
|
|
}
|
2026-01-27 12:10:08 +09:00
|
|
|
|
|
|
|
|
void GSEngineShutdown(GSEngine engine) {
|
|
|
|
|
GSLog(engine, GSLogInfo, "Engine shutdown started");
|
|
|
|
|
|
|
|
|
|
/* TODO: proper shutdown */
|
|
|
|
|
engine->shutdown -= 2;
|
|
|
|
|
}
|