diff --git a/code/foundation/src/core/game.c b/code/foundation/src/core/game.c index 6b5c272..c258686 100644 --- a/code/foundation/src/core/game.c +++ b/code/foundation/src/core/game.c @@ -134,11 +134,12 @@ float game_time() { return (float)get_cached_time(); } -void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) { +void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) { game_mode = play_mode; game_should_close = false; - db_init(); + entity_default_spawnlist(); + game_init(db_init()); #ifndef _DEBUG const char *host_ip = "lab.zakto.pw"; @@ -181,6 +182,8 @@ void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_ //ecs_set_target_fps(world_ecs(), 60); } } + + game_init_ecs(); if (game_mode == GAMEKIND_SINGLE) { for (uint32_t i = 0; i < num_viewers; i++) { diff --git a/code/foundation/src/core/game.h b/code/foundation/src/core/game.h index bd68ea3..accb0ef 100644 --- a/code/foundation/src/core/game.h +++ b/code/foundation/src/core/game.h @@ -11,7 +11,7 @@ typedef enum { FORCE_GAMEKIND_UINT8 = UINT8_MAX } game_kind; -void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled); +void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled); void game_shutdown(); void game_request_close(); uint8_t game_is_running(); @@ -21,6 +21,8 @@ game_kind game_get_kind(void); //~ NOTE(zaklaus): game events // Implemented by games +void game_init(bool new_db); +void game_init_ecs(); // called once the world is initialised void game_input(); void game_update(); void game_render(); diff --git a/code/foundation/src/models/database.c b/code/foundation/src/models/database.c index 994cc26..f6fa60b 100644 --- a/code/foundation/src/models/database.c +++ b/code/foundation/src/models/database.c @@ -28,7 +28,7 @@ void sql_asset(sqlite3_context *ctx, int argc, sqlite3_value **argv) { sqlite3_result_null(ctx); } -void db_init() { +bool db_init() { bool new_db = !zpl_fs_exists(ECO2D_DB); sqlite3_open(ECO2D_DB, &db); assert(db && "Failed to open database."); @@ -37,7 +37,7 @@ void db_init() { sqlite3_create_function(db, "asset", 1, SQLITE_UTF8, NULL, sql_asset, NULL, NULL); if (new_db) { - zpl_printf("[INFO] Creating new database.\n"); + zpl_printf("[INFO] Creating new database...\n"); db_exec_file("art/queries/tables.sql"); assets_db_init(); @@ -48,10 +48,12 @@ void db_init() { } // initialise models db - assets_db(); - blocks_db(); - craft_db(); - item_db(); + zpl_printf("[INFO] Loading models from database...\n"); + assets_db(); zpl_printf("[INFO] Assets loaded.\n"); + blocks_db(); zpl_printf("[INFO] Blocks loaded.\n"); + craft_db(); zpl_printf("[INFO] Recipes loaded.\n"); + item_db(); zpl_printf("[INFO] Items loaded.\n"); + return new_db; } void db_shutdown() { diff --git a/code/foundation/src/models/database.h b/code/foundation/src/models/database.h index 8d49010..50a47a8 100644 --- a/code/foundation/src/models/database.h +++ b/code/foundation/src/models/database.h @@ -2,7 +2,7 @@ #include "platform/system.h" #include "zpl.h" -void db_init(); +bool db_init(); void db_shutdown(); // raw query data getters diff --git a/code/foundation/src/models/entity.c b/code/foundation/src/models/entity.c index ed6e147..940d79a 100644 --- a/code/foundation/src/models/entity.c +++ b/code/foundation/src/models/entity.c @@ -8,8 +8,45 @@ #include "systems/systems.h" #include "zpl.h" +typedef struct { + asset_id id; + uint64_t (*proc)(); + uint64_t (*proc_udata)(void*); +} spawndef; + +static spawndef *entity_spawnlist; + +void entity_add_spawndef(uint16_t id, uint64_t (*proc)()) { + spawndef def={0}; + def.id = id; + def.proc = proc; + zpl_array_append(entity_spawnlist, def); +} + +void entity_add_spawndef_data(uint16_t id, uint64_t (*proc)(void*)) { + spawndef def={0}; + def.id = id; + def.proc_udata = proc; + zpl_array_append(entity_spawnlist, def); +} + // NOTE(zaklaus): bring in entity spawnlist -#include "lists/entity_spawnlist.c" +// #include "lists/entity_spawnlist.c" +#include "models/prefabs/prefabs_list.c" +#define MAX_ENTITY_SPAWNDEFS ((size_t)zpl_array_count(entity_spawnlist)) + +void entity_default_spawnlist(void) { + zpl_array_init(entity_spawnlist, zpl_heap()); + + entity_add_spawndef(ASSET_CHEST, storage_spawn); + entity_add_spawndef(ASSET_FURNACE, furnace_spawn); + entity_add_spawndef(ASSET_CRAFTBENCH, craftbench_spawn); + entity_add_spawndef(ASSET_SPLITTER, splitter_spawn); + entity_add_spawndef(ASSET_ASSEMBLER, assembler_spawn); + entity_add_spawndef(ASSET_CREATURE, creature_spawn); + entity_add_spawndef(ASSET_MOB, mob_spawn); + entity_add_spawndef_data(ASSET_BLUEPRINT, blueprint_spawn_udata); +} uint64_t entity_spawn(uint16_t class_id) { ecs_entity_t e = ecs_new(world_ecs(), 0); diff --git a/code/foundation/src/models/entity.h b/code/foundation/src/models/entity.h index 78dd349..e623874 100644 --- a/code/foundation/src/models/entity.h +++ b/code/foundation/src/models/entity.h @@ -11,6 +11,11 @@ void entity_batch_despawn(uint64_t *ids, size_t num_ids); void entity_despawn(uint64_t ent_id); void entity_set_position(uint64_t ent_id, float x, float y); +// NOTE(zaklaus): spawndef manager + +void entity_add_spawndef(uint16_t id, uint64_t (*proc)()); +void entity_add_spawndef_data(uint16_t id, uint64_t (*proc)(void*)); +void entity_default_spawnlist(void); // NOTE(zaklaus): action-based entity stream throttling void entity_wake(uint64_t ent_id); diff --git a/code/games/minimal/src/game.c b/code/games/minimal/src/game.c index bf19fa6..76b7ff6 100644 --- a/code/games/minimal/src/game.c +++ b/code/games/minimal/src/game.c @@ -1,30 +1,38 @@ -#include "core/game.h" - -void game_input() { - game_core_input(); -} - -void game_update() { - game_core_update(); -} - -void game_render() { - game_core_render(); -} - - -void game_player_joined(uint64_t ent) { - -} - -void game_player_departed(uint64_t ent) { - -} - -void game_player_died(uint64_t ent) { - -} - -void game_client_receive_code(pkt_send_code data) { - -} \ No newline at end of file +#include "core/game.h" + +void game_init(bool new_db) { + +} + +void game_init_ecs() { + +} + +void game_input() { + game_core_input(); +} + +void game_update() { + game_core_update(); +} + +void game_render() { + game_core_render(); +} + + +void game_player_joined(uint64_t ent) { + +} + +void game_player_departed(uint64_t ent) { + +} + +void game_player_died(uint64_t ent) { + +} + +void game_client_receive_code(pkt_send_code data) { + +} diff --git a/code/games/minimal/src/main.c b/code/games/minimal/src/main.c index 7caafe3..418e51e 100644 --- a/code/games/minimal/src/main.c +++ b/code/games/minimal/src/main.c @@ -69,7 +69,7 @@ int main(int argc, char** argv) { } sighandler_register(); - game_init(host, port, play_mode, 1, seed, chunk_size, world_size, 0); + game_setup(host, port, play_mode, 1, seed, chunk_size, world_size, 0); game_run(); diff --git a/code/games/sandbox/src/game.c b/code/games/sandbox/src/game.c index 1ad095c..f648daa 100644 --- a/code/games/sandbox/src/game.c +++ b/code/games/sandbox/src/game.c @@ -1,31 +1,38 @@ -#include "core/game.h" - -void game_input() { - game_core_input(); -} - -void game_update() { - game_core_update(); -} - -void game_render() { - game_core_render(); -} - - -void game_player_joined(uint64_t ent) { - ecs_set(world_ecs(), ent, Inventory, {0}); - ecs_set(world_ecs(), ent, HealthRegen, {15.f}); -} - -void game_player_departed(uint64_t ent) { - -} - -void game_player_died(uint64_t ent) { - -} - -void game_client_receive_code(pkt_send_code data) { - -} \ No newline at end of file +#include "core/game.h" + +void game_init(bool new_db) { + +} + +void game_init_ecs() { + +} + +void game_input() { + game_core_input(); +} + +void game_update() { + game_core_update(); +} + +void game_render() { + game_core_render(); +} + +void game_player_joined(uint64_t ent) { + ecs_set(world_ecs(), ent, Inventory, {0}); + ecs_set(world_ecs(), ent, HealthRegen, {15.f}); +} + +void game_player_departed(uint64_t ent) { + +} + +void game_player_died(uint64_t ent) { + +} + +void game_client_receive_code(pkt_send_code data) { + +} diff --git a/code/games/sandbox/src/main.c b/code/games/sandbox/src/main.c index 8327227..3356dfa 100644 --- a/code/games/sandbox/src/main.c +++ b/code/games/sandbox/src/main.c @@ -73,7 +73,7 @@ int main(int argc, char** argv) { } sighandler_register(); - game_init(host, port, play_mode, num_viewers, seed, chunk_size, world_size, is_dash_enabled); + game_setup(host, port, play_mode, num_viewers, seed, chunk_size, world_size, is_dash_enabled); game_run(); diff --git a/code/games/survival/src/game.c b/code/games/survival/src/game.c index 5ee085a..ef9b7b5 100644 --- a/code/games/survival/src/game.c +++ b/code/games/survival/src/game.c @@ -1,134 +1,138 @@ -#include "core/game.h" -#include "game.h" -#include "world/world.h" -#include "models/components.h" -#include "systems/systems.h" -#include "models/entity.h" -#include "world/entity_view.h" - -#include "gui/notifications.h" - -float get_rand_between(float min, float max) { - return ((float)rand() / (float)RAND_MAX) * (max - min) + min; -} - -static ecs_query_t *ecs_mobpos_query = NULL; -static ecs_query_t *ecs_pawn_query = NULL; - -// custom systems -#include "system_mob.c" -#include "system_weapon.c" - -#define PLAYER_RESPAWN_BLAST_FORCE 1200.0f - -void PlayerRespawn(ecs_iter_t *it) { - Respawn *r = ecs_field(it, Respawn, 1); - Input *in = ecs_field(it, Input, 2); - Sprite *s = ecs_field(it, Sprite, 3); - Position *p = ecs_field(it, Position, 4); - Health *h = ecs_field(it, Health, 5); - - for (int i = 0; i < it->count; i++) { - if (r[i].timer > 0) { - TICK_VAR(r[i].timer); - continue; - } - - ecs_remove(it->world, it->entities[i], Respawn); - ecs_remove(it->world, it->entities[i], Dead); - in[i].is_blocked = 0; - s[i].spritesheet = 0; - h[i].hp = h[i].max_hp; - - size_t ents_count; - int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2); - - for (size_t j = 0; j < ents_count; j++) { - uint64_t ent_id = ents[j]; - - if (!ecs_get(it->world, ent_id, Mob) || ecs_get(it->world, ent_id, Dead)) { - continue; - } - - const Position *p2 = ecs_get(it->world, ent_id, Position); - Velocity *v = ecs_get_mut(it->world, ent_id, Velocity); - float dx = p2->x - p[i].x; - float dy = p2->y - p[i].y; - float range = zpl_sqrt(dx*dx + dy*dy); - if (range <= 5*WORLD_BLOCK_SIZE) { - Health *hp = ecs_get_mut(it->world, ent_id, Health); - hp->dmg += hp->max_hp/2.0f; - - v->x += (dx/range)*PLAYER_RESPAWN_BLAST_FORCE; - v->y += (dy/range)*PLAYER_RESPAWN_BLAST_FORCE; - } - } - } -} - -void mob_systems(ecs_world_t *ecs) { - ECS_SYSTEM_TICKED_EX(ecs, MobDetectPlayers, EcsPostUpdate, 100.0f, components.Position, components.Mob, !components.Dead); - ECS_SYSTEM(ecs, MobMovement, EcsPostUpdate, components.Velocity, components.Position, components.MobHuntPlayer, !components.Dead); - ECS_SYSTEM_TICKED(ecs, MobMeleeAtk, EcsPostUpdate, components.Position, components.Mob, components.MobHuntPlayer, components.MobMelee, !components.Dead); - ECS_SYSTEM_TICKED(ecs, MobDespawnDead, EcsPostUpdate, components.Mob, components.Dead); - ECS_SYSTEM_TICKED(ecs, MobSpawner, EcsPostUpdate, components.Input, components.Position, !components.Dead); - ECS_SYSTEM_TICKED(ecs, PlayerRespawn, EcsPostUpdate, components.Respawn, components.Input, components.Sprite, components.Position, components.Health); - - //NOTE(DavoSK): weapons - ecs_mobpos_query = ecs_query_new(world_ecs(), "components.Mob, components.Position, components.Health, components.Velocity, !components.Dead"); - ecs_pawn_query = ecs_query_new(world_ecs(), "components.Position, components.Health, components.Velocity, !components.Dead"); - ECS_SYSTEM_TICKED(ecs, WeaponKnifeMechanic, EcsPostUpdate, components.WeaponKnife, components.Position, components.Input, !components.Dead); - ECS_SYSTEM_TICKED(ecs, WeaponProjectileHit, EcsPostUpdate, components.WeaponProjectile, components.Position, components.Rotation); - ECS_SYSTEM_TICKED(ecs, WeaponProjectileExpire, EcsPostUpdate, components.WeaponProjectile, components.Position); - ECS_OBSERVER(ecs, MobOnDead, EcsOnAdd, components.Mob, components.Sprite, components.Velocity, components.Dead); -} - -void game_input() { - game_core_input(); -} - -void game_update() { - game_core_update(); -} - -void game_render() { - game_core_render(); -} - -void game_setup_ecs() { - mob_systems(world_ecs()); -} - -void game_player_departed(uint64_t ent) { - -} - -void game_player_joined(uint64_t ent) { - notification_push("test1", "Hello World!"); - - //NOTE(DavoSK): add weapon component for testing - ecs_world_t* world = world_ecs(); - ecs_set(world, (ecs_entity_t)ent, WeaponKnife, { - .projectile_count = 10, - .damage = 10, - .spawn_delay = WEAPON_KNIFE_SPAWN_DELAY - }); -} - -void game_player_died(uint64_t ent) { - Sprite *spr = ecs_get_mut(world_ecs(), ent, Sprite); - Velocity *v = ecs_get_mut(world_ecs(), ent, Velocity); - spr->frame = 3 + (rand()%5); - spr->spritesheet = 69; /*special code*/ - *v = (Velocity){0.0f, 0.0f}; - ecs_remove(world_ecs(), ent, PhysicsBody); - ecs_set(world_ecs(), ent, Respawn, { 100 }); -} - -void game_client_receive_code(pkt_send_code data) { - switch (data.code) { - case SURV_CODE_SHOW_NOTIF: { - notification_push("TEST", data.data); - } break; - } -} +#include "core/game.h" +#include "game.h" +#include "world/world.h" +#include "models/components.h" +#include "systems/systems.h" +#include "models/entity.h" +#include "world/entity_view.h" + +#include "gui/notifications.h" + +float get_rand_between(float min, float max) { + return ((float)rand() / (float)RAND_MAX) * (max - min) + min; +} + +static ecs_query_t *ecs_mobpos_query = NULL; +static ecs_query_t *ecs_pawn_query = NULL; + +// custom systems +#include "system_mob.c" +#include "system_weapon.c" + +#define PLAYER_RESPAWN_BLAST_FORCE 1200.0f + +void PlayerRespawn(ecs_iter_t *it) { + Respawn *r = ecs_field(it, Respawn, 1); + Input *in = ecs_field(it, Input, 2); + Sprite *s = ecs_field(it, Sprite, 3); + Position *p = ecs_field(it, Position, 4); + Health *h = ecs_field(it, Health, 5); + + for (int i = 0; i < it->count; i++) { + if (r[i].timer > 0) { + TICK_VAR(r[i].timer); + continue; + } + + ecs_remove(it->world, it->entities[i], Respawn); + ecs_remove(it->world, it->entities[i], Dead); + in[i].is_blocked = 0; + s[i].spritesheet = 0; + h[i].hp = h[i].max_hp; + + size_t ents_count; + int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2); + + for (size_t j = 0; j < ents_count; j++) { + uint64_t ent_id = ents[j]; + + if (!ecs_get(it->world, ent_id, Mob) || ecs_get(it->world, ent_id, Dead)) { + continue; + } + + const Position *p2 = ecs_get(it->world, ent_id, Position); + Velocity *v = ecs_get_mut(it->world, ent_id, Velocity); + float dx = p2->x - p[i].x; + float dy = p2->y - p[i].y; + float range = zpl_sqrt(dx*dx + dy*dy); + if (range <= 5*WORLD_BLOCK_SIZE) { + Health *hp = ecs_get_mut(it->world, ent_id, Health); + hp->dmg += hp->max_hp/2.0f; + + v->x += (dx/range)*PLAYER_RESPAWN_BLAST_FORCE; + v->y += (dy/range)*PLAYER_RESPAWN_BLAST_FORCE; + } + } + } +} + +void mob_systems(ecs_world_t *ecs) { + ECS_SYSTEM_TICKED_EX(ecs, MobDetectPlayers, EcsPostUpdate, 100.0f, components.Position, components.Mob, !components.Dead); + ECS_SYSTEM(ecs, MobMovement, EcsPostUpdate, components.Velocity, components.Position, components.MobHuntPlayer, !components.Dead); + ECS_SYSTEM_TICKED(ecs, MobMeleeAtk, EcsPostUpdate, components.Position, components.Mob, components.MobHuntPlayer, components.MobMelee, !components.Dead); + ECS_SYSTEM_TICKED(ecs, MobDespawnDead, EcsPostUpdate, components.Mob, components.Dead); + ECS_SYSTEM_TICKED(ecs, MobSpawner, EcsPostUpdate, components.Input, components.Position, !components.Dead); + ECS_SYSTEM_TICKED(ecs, PlayerRespawn, EcsPostUpdate, components.Respawn, components.Input, components.Sprite, components.Position, components.Health); + + //NOTE(DavoSK): weapons + ecs_mobpos_query = ecs_query_new(world_ecs(), "components.Mob, components.Position, components.Health, components.Velocity, !components.Dead"); + ecs_pawn_query = ecs_query_new(world_ecs(), "components.Position, components.Health, components.Velocity, !components.Dead"); + ECS_SYSTEM_TICKED(ecs, WeaponKnifeMechanic, EcsPostUpdate, components.WeaponKnife, components.Position, components.Input, !components.Dead); + ECS_SYSTEM_TICKED(ecs, WeaponProjectileHit, EcsPostUpdate, components.WeaponProjectile, components.Position, components.Rotation); + ECS_SYSTEM_TICKED(ecs, WeaponProjectileExpire, EcsPostUpdate, components.WeaponProjectile, components.Position); + ECS_OBSERVER(ecs, MobOnDead, EcsOnAdd, components.Mob, components.Sprite, components.Velocity, components.Dead); +} + +void game_init(bool new_db) { + +} + +void game_input() { + game_core_input(); +} + +void game_update() { + game_core_update(); +} + +void game_render() { + game_core_render(); +} + +void game_init_ecs() { + mob_systems(world_ecs()); +} + +void game_player_departed(uint64_t ent) { + +} + +void game_player_joined(uint64_t ent) { + notification_push("test1", "Hello World!"); + + //NOTE(DavoSK): add weapon component for testing + ecs_world_t* world = world_ecs(); + ecs_set(world, (ecs_entity_t)ent, WeaponKnife, { + .projectile_count = 10, + .damage = 10, + .spawn_delay = WEAPON_KNIFE_SPAWN_DELAY + }); +} + +void game_player_died(uint64_t ent) { + Sprite *spr = ecs_get_mut(world_ecs(), ent, Sprite); + Velocity *v = ecs_get_mut(world_ecs(), ent, Velocity); + spr->frame = 3 + (rand()%5); + spr->spritesheet = 69; /*special code*/ + *v = (Velocity){0.0f, 0.0f}; + ecs_remove(world_ecs(), ent, PhysicsBody); + ecs_set(world_ecs(), ent, Respawn, { 100 }); +} + +void game_client_receive_code(pkt_send_code data) { + switch (data.code) { + case SURV_CODE_SHOW_NOTIF: { + notification_push("TEST", data.data); + } break; + } +} diff --git a/code/games/survival/src/main.c b/code/games/survival/src/main.c index 471f2db..3709656 100644 --- a/code/games/survival/src/main.c +++ b/code/games/survival/src/main.c @@ -90,8 +90,7 @@ int main(int argc, char** argv) { } sighandler_register(); - game_init(host, port, play_mode, 1, seed, chunk_size, world_size, is_dash_enabled); - game_setup_ecs(); + game_setup(host, port, play_mode, 1, seed, chunk_size, world_size, is_dash_enabled); game_run(); game_shutdown();