From 1a5ef9e8fcfd5be90b9c1662c4761f41ba825a78 Mon Sep 17 00:00:00 2001 From: Vladyslav Hrytsenko Date: Mon, 13 Feb 2023 10:12:32 +0200 Subject: [PATCH] meta: foundation draft --- code/games/minimal/CMakeLists.txt | 2 +- code/games/minimal/src/main.c | 81 +------ code/games/minimal/src/oldmain.c | 82 +++++++ code/games/survival/CMakeLists.txt | 2 +- code/games/survival/src/main.c | 378 +++++++++++++++++++++++------ code/games/survival/src/oldmain.c | 101 ++++++++ foundation.md | 64 +++++ 7 files changed, 550 insertions(+), 160 deletions(-) create mode 100644 code/games/minimal/src/oldmain.c create mode 100644 code/games/survival/src/oldmain.c create mode 100644 foundation.md diff --git a/code/games/minimal/CMakeLists.txt b/code/games/minimal/CMakeLists.txt index 578ca24..449c5ba 100644 --- a/code/games/minimal/CMakeLists.txt +++ b/code/games/minimal/CMakeLists.txt @@ -1,5 +1,5 @@ add_executable(minimal - src/main.c + src/oldmain.c src/platform.c src/worldgen.c src/texgen.c diff --git a/code/games/minimal/src/main.c b/code/games/minimal/src/main.c index 7caafe3..4196a6f 100644 --- a/code/games/minimal/src/main.c +++ b/code/games/minimal/src/main.c @@ -1,82 +1,5 @@ -#define ZPL_IMPL -#include "zpl.h" -#include "platform/system.h" -#include "core/game.h" -#include "models/entity.h" -#include "world/entity_view.h" -#include "utils/options.h" -#include "platform/signal_handling.h" -#include "platform/profiler.h" +typedef int efd_main; -#include "flecs.h" -#include "flecs/flecs_os_api_stdcpp.h" - -#include "models/components.h" -#include "systems/systems.h" - -#include "platform/arch.h" - -#define DEFAULT_WORLD_SEED 302097 -#define DEFAULT_CHUNK_SIZE 16 /* amount of blocks within a chunk (single axis) */ -#define DEFAULT_WORLD_SIZE 5 /* amount of chunks within a world (single axis) */ - -int main(int argc, char** argv) { - zpl_opts opts={0}; - zpl_opts_init(&opts, zpl_heap(), argv[0]); - - zpl_opts_add(&opts, "?", "help", "the HELP section", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "v", "viewer-only", "run viewer-only client", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "d", "server-only", "run dedicated server", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "p", "preview-map", "draw world preview", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "s", "seed", "world seed", ZPL_OPTS_INT); - zpl_opts_add(&opts, "r", "random-seed", "generate random world seed", ZPL_OPTS_FLAG); - //zpl_opts_add(&opts, "cs", "chunk-size", "amount of blocks within a chunk (single axis)", ZPL_OPTS_INT); - zpl_opts_add(&opts, "ws", "world-size", "amount of chunks within a world (single axis)", ZPL_OPTS_INT); - zpl_opts_add(&opts, "ip", "host", "host IP address", ZPL_OPTS_STRING); - zpl_opts_add(&opts, "port", "port", "port number", ZPL_OPTS_INT); - - uint32_t ok = zpl_opts_compile(&opts, argc, argv); - - if (!ok) { - zpl_opts_print_errors(&opts); - zpl_opts_print_help(&opts); - return -1; - } - - int8_t is_viewer_only = zpl_opts_has_arg(&opts, "viewer-only"); - int8_t is_server_only = zpl_opts_has_arg(&opts, "server-only"); - int32_t seed = (int32_t)zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED); - uint16_t world_size = (uint16_t)zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE); - uint16_t chunk_size = DEFAULT_CHUNK_SIZE; //zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE); - zpl_string host = zpl_opts_string(&opts, "host", NULL); - uint16_t port = (uint16_t)zpl_opts_integer(&opts, "port", 0); - - game_kind play_mode = GAMEKIND_SINGLE; - - if (is_viewer_only) play_mode = GAMEKIND_CLIENT; - if (is_server_only) play_mode = GAMEKIND_HEADLESS; - - if (zpl_opts_has_arg(&opts, "random-seed")) { - zpl_random rnd={0}; - zpl_random_init(&rnd); - seed = zpl_random_gen_u32(&rnd); - zpl_printf("Seed: %u\n", seed); - } - - if (zpl_opts_has_arg(&opts, "preview-map")) { - generate_minimap(seed, WORLD_BLOCK_SIZE, chunk_size, world_size); - return 0; - } - - sighandler_register(); - game_init(host, port, play_mode, 1, seed, chunk_size, world_size, 0); - - game_run(); - - game_shutdown(); - sighandler_unregister(); - - zpl_string_free(host); - zpl_opts_free(&opts); +efd_main start() { return 0; } diff --git a/code/games/minimal/src/oldmain.c b/code/games/minimal/src/oldmain.c new file mode 100644 index 0000000..7caafe3 --- /dev/null +++ b/code/games/minimal/src/oldmain.c @@ -0,0 +1,82 @@ +#define ZPL_IMPL +#include "zpl.h" +#include "platform/system.h" +#include "core/game.h" +#include "models/entity.h" +#include "world/entity_view.h" +#include "utils/options.h" +#include "platform/signal_handling.h" +#include "platform/profiler.h" + +#include "flecs.h" +#include "flecs/flecs_os_api_stdcpp.h" + +#include "models/components.h" +#include "systems/systems.h" + +#include "platform/arch.h" + +#define DEFAULT_WORLD_SEED 302097 +#define DEFAULT_CHUNK_SIZE 16 /* amount of blocks within a chunk (single axis) */ +#define DEFAULT_WORLD_SIZE 5 /* amount of chunks within a world (single axis) */ + +int main(int argc, char** argv) { + zpl_opts opts={0}; + zpl_opts_init(&opts, zpl_heap(), argv[0]); + + zpl_opts_add(&opts, "?", "help", "the HELP section", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "v", "viewer-only", "run viewer-only client", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "d", "server-only", "run dedicated server", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "p", "preview-map", "draw world preview", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "s", "seed", "world seed", ZPL_OPTS_INT); + zpl_opts_add(&opts, "r", "random-seed", "generate random world seed", ZPL_OPTS_FLAG); + //zpl_opts_add(&opts, "cs", "chunk-size", "amount of blocks within a chunk (single axis)", ZPL_OPTS_INT); + zpl_opts_add(&opts, "ws", "world-size", "amount of chunks within a world (single axis)", ZPL_OPTS_INT); + zpl_opts_add(&opts, "ip", "host", "host IP address", ZPL_OPTS_STRING); + zpl_opts_add(&opts, "port", "port", "port number", ZPL_OPTS_INT); + + uint32_t ok = zpl_opts_compile(&opts, argc, argv); + + if (!ok) { + zpl_opts_print_errors(&opts); + zpl_opts_print_help(&opts); + return -1; + } + + int8_t is_viewer_only = zpl_opts_has_arg(&opts, "viewer-only"); + int8_t is_server_only = zpl_opts_has_arg(&opts, "server-only"); + int32_t seed = (int32_t)zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED); + uint16_t world_size = (uint16_t)zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE); + uint16_t chunk_size = DEFAULT_CHUNK_SIZE; //zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE); + zpl_string host = zpl_opts_string(&opts, "host", NULL); + uint16_t port = (uint16_t)zpl_opts_integer(&opts, "port", 0); + + game_kind play_mode = GAMEKIND_SINGLE; + + if (is_viewer_only) play_mode = GAMEKIND_CLIENT; + if (is_server_only) play_mode = GAMEKIND_HEADLESS; + + if (zpl_opts_has_arg(&opts, "random-seed")) { + zpl_random rnd={0}; + zpl_random_init(&rnd); + seed = zpl_random_gen_u32(&rnd); + zpl_printf("Seed: %u\n", seed); + } + + if (zpl_opts_has_arg(&opts, "preview-map")) { + generate_minimap(seed, WORLD_BLOCK_SIZE, chunk_size, world_size); + return 0; + } + + sighandler_register(); + game_init(host, port, play_mode, 1, seed, chunk_size, world_size, 0); + + game_run(); + + game_shutdown(); + sighandler_unregister(); + + zpl_string_free(host); + zpl_opts_free(&opts); + return 0; +} diff --git a/code/games/survival/CMakeLists.txt b/code/games/survival/CMakeLists.txt index cca030d..389087c 100644 --- a/code/games/survival/CMakeLists.txt +++ b/code/games/survival/CMakeLists.txt @@ -1,5 +1,5 @@ add_executable(survival - src/main.c + src/oldmain.c src/platform.c src/worldgen.c src/texgen.c diff --git a/code/games/survival/src/main.c b/code/games/survival/src/main.c index 4c94411..8465ade 100644 --- a/code/games/survival/src/main.c +++ b/code/games/survival/src/main.c @@ -1,101 +1,321 @@ -#define ZPL_IMPL -#include "zpl.h" -#include "platform/system.h" -#include "core/game.h" -#include "game.h" -#include "models/entity.h" -#include "world/entity_view.h" -#include "utils/options.h" -#include "platform/signal_handling.h" -#include "platform/profiler.h" +#include +#include +#include -#include "flecs.h" -#include "flecs/flecs_os_api_stdcpp.h" +/// lib.c -#include "models/components.h" -#include "systems/systems.h" +// core -#include "platform/arch.h" +typedef int efd_app; +typedef uint16_t efd_entity_type; +typedef int32_t efd_result; +typedef uint64_t efd_entity; -ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0) -#include "tinyc2.h" -ZPL_DIAGNOSTIC_POP +typedef enum efd_asset_type { + // EFD_ASSET_NONE = 0, + EFD_ASSET_TEXTURE, + EFD_ASSET_ANIMATION, + EFD_ASSET_SOUND, + EFD_ASSET_FONT, + EFD_ASSET_SHADER, + EFD_ASSET_COUNT_TYPES, +} efd_asset_type; -#define DEFAULT_WORLD_SEED 302097 -#define DEFAULT_CHUNK_SIZE 16 /* amount of blocks within a chunk (single axis) */ -#define DEFAULT_WORLD_SIZE 5 /* amount of chunks within a world (single axis) */ +typedef struct efd_app_desc { + const char *name; + int debug_ui; -/* - TODO - - monster spawner - - the longer we survive, the more and stronger enemies we spawn - - player grows HP by leveling up - - XP increases by killing mobs - - player can pick an "ability" upon reaching level milestones - - abilities: armor/shield, TODO ... - - enemies damage player when close to him in ticks (damage effects, ...) - - basic projectile pooling (flecs) - - somewhat believable world gen, small hamlets with cols, etc -*/ + int width; + int height; + int fullscreen; + int vsync; + int server_only; + int viewer_only; + int viewer_amount; + int world_seed; + int world_seed_random; -int main(int argc, char** argv) { - zpl_opts opts={0}; - zpl_opts_init(&opts, zpl_heap(), argv[0]); + efd_result (*init_cb)(); + efd_result (*update_cb)(); + efd_result (*render_cb)(efd_entity_type type); + efd_result (*player_join_cb)(efd_entity player_id); + efd_result (*player_leave_cb)(efd_entity player_id); + efd_result (*cleanup_cb)(); - zpl_opts_add(&opts, "?", "help", "the HELP section", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "v", "viewer-only", "run viewer-only client", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "d", "server-only", "run dedicated server", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "p", "preview-map", "draw world preview", ZPL_OPTS_FLAG); - zpl_opts_add(&opts, "s", "seed", "world seed", ZPL_OPTS_INT); - zpl_opts_add(&opts, "r", "random-seed", "generate random world seed", ZPL_OPTS_FLAG); - //zpl_opts_add(&opts, "cs", "chunk-size", "amount of blocks within a chunk (single axis)", ZPL_OPTS_INT); - zpl_opts_add(&opts, "ws", "world-size", "amount of chunks within a world (single axis)", ZPL_OPTS_INT); - zpl_opts_add(&opts, "ip", "host", "host IP address", ZPL_OPTS_STRING); - zpl_opts_add(&opts, "port", "port", "port number", ZPL_OPTS_INT); + struct { + float item_pickup_radius; + float item_merge_radius; + float item_drop_radius; + float item_attract_radius; + float item_attract_force; + } rules; +} efd_app_desc; - uint32_t ok = zpl_opts_compile(&opts, argc, argv); +// assets - if (!ok) { - zpl_opts_print_errors(&opts); - zpl_opts_print_help(&opts); - return -1; +// #define EFD_ASSET_TEXTURE_LAST 15 +// #define EFD_ASSET_ANIMATION_LAST 2222222 +// #define EFD_ASSET_ANIMATION_LAST 2222222 + +// #define CONC(a, b) a##b +/* + CONC(type, _LAST) */ + +#define EFD_ASSET_SHIFT 16 +#define EFD_ASSET(type) ((type) << EFD_ASSET_SHIFT) +#define EFD_ASSET_TYPE(id) ((id) >> EFD_ASSET_SHIFT) + +typedef struct efd_asset { + int id; + const char *path; + void *data; /* TODO: make a union */ +} efd_asset; + +efd_result efd_asset_add(int id, const char *path); +efd_result efd_asset_remove(int id); +efd_asset *efd_asset_get(int id); + +// notifications + +efd_result efd_notify_push(efd_entity actor, const char *title, const char *text, float duration); +efd_result efd_notify_clear(efd_entity actor); + +// tooltips + +efd_result efd_tooltip_add(const char *name, const char *text); +efd_result efd_tooltip_remove(const char *name); + +// entities + +enum efd_entity_type_builtins { + EFD_ENTITY_NONE = 0, + EFD_ENTITY_PLAYER = 1, + EFD_ENTITY_CHUNK, + EFD_ENTITY_OBJECT, + EFD_ENTITY_ITEM, + EFD_ENTITY_NPC, + EFD_ENTITY_VEHICLE, + + EFD_ENTITY_TYPE_LAST, + EFD_ENTITY_TYPE_MAX = 0xFFFF, +}; + +/// app.c + +enum { + /* textures */ + ASSET_TILE_DIRT = EFD_ASSET(EFD_ASSET_TEXTURE), + ASSET_TILE_GRASS, + ASSET_TILE_STONE, + + ASSET_BLOCK_STONE, + ASSET_BLOCK_BRICK, + + ASSET_PLAYER, + ASSET_TREE, + ASSET_CHEST, + ASSET_MONSTER, + + /* animations */ + ASSET_PLAYER_ANIM = EFD_ASSET(EFD_ASSET_ANIMATION), + + /* sounds */ + ASSET_PLAYER_SOUND = EFD_ASSET(EFD_ASSET_SOUND), + ASSET_TREE_SOUND, + ASSET_CHEST_SOUND, + + /* fonts */ + ASSET_FONT_DEFAULT = EFD_ASSET(EFD_ASSET_FONT), +}; + +enum { + ENTITY_MONSTER = EFD_ENTITY_TYPE_LAST, + ENTITY_WEAPON, +}; + +void Move(ecs_iter_t *it) { + // Get fields from system query + Position *p = ecs_field(it, Position, 1); + Velocity *v = ecs_field(it, Velocity, 2); + + // Iterate matched entities + for (int i = 0; i < it->count, i++) { + p[i].x += v[i].x; + p[i].y += v[i].y; + } +} + +efd_result init() { + // register assets + { + // register textures (tiles) + efd_asset_add(ASSET_TILE_DIRT, "assets/tile_dirt.png"); + efd_asset_add(ASSET_TILE_GRASS, "assets/tilegrass.png"); + efd_asset_add(ASSET_TILE_STONE, "assets/tilestone.png"); + + // register textures (blocks) + efd_asset_add(ASSET_BLOCK_STONE, "assets/block_stone.png"); + efd_asset_add(ASSET_BLOCK_BRICK, "assets/block_brick.png"); + + // register textures (entities) + efd_asset_add(ASSET_PLAYER, "assets/player.png"); + efd_asset_add(ASSET_TREE, "assets/tree.png"); + efd_asset_add(ASSET_CHEST, "assets/chest.png"); + efd_asset_add(ASSET_MONSTER, "assets/monster.png"); + + // register animations + efd_asset_add(ASSET_PLAYER_ANIM, "assets/player.anim"); + + // register sounds + efd_asset_add(ASSET_PLAYER_SOUND, "assets/player.ogg"); + efd_asset_add(ASSET_TREE_SOUND, "assets/tree.ogg"); + + // register fonts + efd_asset_add(ASSET_FONT_DEFAULT, "assets/font.ttf"); } - int8_t is_viewer_only = zpl_opts_has_arg(&opts, "viewer-only"); - int8_t is_server_only = zpl_opts_has_arg(&opts, "server-only"); - int32_t seed = (int32_t)zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED); - uint16_t world_size = (uint16_t)zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE); - uint16_t chunk_size = DEFAULT_CHUNK_SIZE; //zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE); - zpl_string host = zpl_opts_string(&opts, "host", NULL); - uint16_t port = (uint16_t)zpl_opts_integer(&opts, "port", 0); + // define world generation rules, load existing world + // or set up a custom pipeline to generate a new one + // efd_world_load("worlds/default.json"); - game_kind play_mode = GAMEKIND_SINGLE; + // register tooltips + efd_tooltip_add("ASSET_TREE", "A tree, it's a tree, what do you expect?"); + efd_tooltip_add("ASSET_CHEST", "A chest, it's a chest, what do you expect?"); - if (is_viewer_only) play_mode = GAMEKIND_CLIENT; - if (is_server_only) play_mode = GAMEKIND_HEADLESS; + // 1. define itself + // 2. render itself + // 3. register types for sedning data + // 4. define systems and components - if (zpl_opts_has_arg(&opts, "random-seed")) { - zpl_random rnd={0}; - zpl_random_init(&rnd); - seed = zpl_random_gen_u32(&rnd); - zpl_printf("Seed: %u\n", seed); - } + ECS_SYSTEM(efd_world(), Move, EcsOnUpdate, Position, [in] Velocity); - if (zpl_opts_has_arg(&opts, "preview-map")) { - generate_minimap(seed, WORLD_BLOCK_SIZE, chunk_size, world_size); - return 0; - } + // register game specific input bindings + // pre-defined bindings and controlsets + efd_controlset_apply(EFD_ACTION_MOVE, EFD_CONTROLSET_WASD | EFD_CONTROLSET_ARROWS | EFD_CONTROLSET_GAMEPAD_LEFT); + efd_controlset_apply(EFD_ACTION_POINT, EFD_CONTROLSET_MOUSE | EFD_CONTROLSET_GAMEPAD_RIGHT); - sighandler_register(); - game_init(host, port, play_mode, 1, seed, chunk_size, world_size, 0); - game_setup_ecs(); - game_run(); + // custom bindings and controlsets + efd_controlset_keyboard(CONTROLSET_ACCELERATE, EFD_KEY_DOWN, EFD_KEY_SHIFT_LEFT | EFD_KEY_SHIFT_RIGHT); + efd_controlset_gamepad(CONTROLSET_ACCELERATE, EFD_GAMEPAD_LEFT_TRIGGER, 0.5f); + efd_controlset_apply(EFD_ACTION_SPRINT, CONTROLSET_ACCERLATE); - game_shutdown(); - sighandler_unregister(); + // custom input bindings for custom actions + efd_controlset_register(ACTION_USE); + efd_controlset_keyboard(CONTROLSET_USE, EFD_KEY_DOWN, EFD_KEY_E); + efd_controlset_gamepad(CONTROLSET_USE, EFD_GAMEPAD_BUTTON_A, 0.5f); + efd_controlset_apply(ACTION_USE, CONTROLSET_USE); + + return 0; +} + +efd_result update() { + return 0; +} + +efd_result render(efd_entity_type type) { + switch (type) { + case EFD_ENTITY_PLAYER: + /* additional/replacable rendering code on top of what EFD provides for built-in types */ + efd_render_texture(ASSET_PLAYER, 0, 0, 0, 0, 0, 0, 0, 0); + + return 1; /* we handled the rendering, don't render with the default renderer */ + break; + + case ENTITY_MONSTER: + /* our custom rendering code for monster */ + efd_render_texture(ASSET_MONSTER, 0, 0, 0, 0, 0, 0, 0, 0); + break; + + case ENTITY_WEAPON: + /* our custom rendering code for weapon */ + break; + } + + return 0; +} + +efd_result player_join(efd_entity player) { + efd_notify_push(player, "Test", "Welcome to the game!", 5.0f); + return 0; +} + +efd_result player_leave(efd_entity player) { + return 0; +} + +efd_result cleanup() { + return 0; +} + +efd_app_desc efd_main() { + return (efd_app_desc){ + .name = "Survival", + .debug_ui = true, + + /* these are defaults, with zpl_option/config files overrides */ + .width = 1280, + .height = 720, + .fullscreen = 0, + .vsync = 1, + + /* these are code overrides for zpl_option flags (not defaults) */ + .server_only = false, + .viewer_only = false, + .viewer_amount = 1, + .world_seed = 0, + .world_seed_random = true, + + /* primary callbacks */ + .init_cb = init, + .update_cb = update, + .render_cb = render, + .player_join_cb = player_join, + .player_leave_cb = player_leave, + .cleanup_cb = cleanup, + + .rules = { + .item_pickup_radius = 25.0f, + .item_merge_radius = 75.0f, + .item_drop_radius = 15.0f, + .item_attract_radius = 75.0f, + .item_attract_force = 0.1f, + }, + }; +} + +/// test.c + +#include + +efd_result efd_asset_add(int id, const char *path) { + printf("asset_add: %d, %s\n", id, path); + return 0; +} + +efd_result efd_tooltip_add(const char *id, const char *text) { + printf("tooltip_add: %s, %s\n", id, text); + return 0; +} + +efd_result efd_notify_push(efd_entity player, const char *title, const char *text, float duration) { + printf("notify_push: %llu, %s, %s, %f\n", player, title, text, duration); + return 0; +} + +void test(efd_entity_type type) { printf("type: %d\n", type); } + +int main(int argc, char **argv) { + efd_app_desc desc = efd_main(); + printf("value: %f\n", desc.rules.item_pickup_radius); + printf("ASSET_TILE_DIRT: %d\n", ASSET_TILE_DIRT); + printf("ASSET_TILE_GRASS: %d\n", ASSET_TILE_GRASS); + printf("ASSET_PLAYER: %d\n", ASSET_PLAYER); + printf("ASSET_CHEST: %d\n", ASSET_CHEST); + printf("ASSET_PLAYER_ANIM: %d\n", ASSET_PLAYER_ANIM); + printf("ASSET_PLAYER_SOUND: %d\n", ASSET_PLAYER_SOUND); + printf("ASSET_TREE_SOUND: %d\n", ASSET_TREE_SOUND); + + desc.init_cb(); - zpl_string_free(host); - zpl_opts_free(&opts); return 0; } diff --git a/code/games/survival/src/oldmain.c b/code/games/survival/src/oldmain.c new file mode 100644 index 0000000..4c94411 --- /dev/null +++ b/code/games/survival/src/oldmain.c @@ -0,0 +1,101 @@ +#define ZPL_IMPL +#include "zpl.h" +#include "platform/system.h" +#include "core/game.h" +#include "game.h" +#include "models/entity.h" +#include "world/entity_view.h" +#include "utils/options.h" +#include "platform/signal_handling.h" +#include "platform/profiler.h" + +#include "flecs.h" +#include "flecs/flecs_os_api_stdcpp.h" + +#include "models/components.h" +#include "systems/systems.h" + +#include "platform/arch.h" + +ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0) +#include "tinyc2.h" +ZPL_DIAGNOSTIC_POP + +#define DEFAULT_WORLD_SEED 302097 +#define DEFAULT_CHUNK_SIZE 16 /* amount of blocks within a chunk (single axis) */ +#define DEFAULT_WORLD_SIZE 5 /* amount of chunks within a world (single axis) */ + +/* + TODO + - monster spawner + - the longer we survive, the more and stronger enemies we spawn + - player grows HP by leveling up + - XP increases by killing mobs + - player can pick an "ability" upon reaching level milestones + - abilities: armor/shield, TODO ... + - enemies damage player when close to him in ticks (damage effects, ...) + - basic projectile pooling (flecs) + - somewhat believable world gen, small hamlets with cols, etc +*/ + + +int main(int argc, char** argv) { + zpl_opts opts={0}; + zpl_opts_init(&opts, zpl_heap(), argv[0]); + + zpl_opts_add(&opts, "?", "help", "the HELP section", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "v", "viewer-only", "run viewer-only client", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "d", "server-only", "run dedicated server", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "p", "preview-map", "draw world preview", ZPL_OPTS_FLAG); + zpl_opts_add(&opts, "s", "seed", "world seed", ZPL_OPTS_INT); + zpl_opts_add(&opts, "r", "random-seed", "generate random world seed", ZPL_OPTS_FLAG); + //zpl_opts_add(&opts, "cs", "chunk-size", "amount of blocks within a chunk (single axis)", ZPL_OPTS_INT); + zpl_opts_add(&opts, "ws", "world-size", "amount of chunks within a world (single axis)", ZPL_OPTS_INT); + zpl_opts_add(&opts, "ip", "host", "host IP address", ZPL_OPTS_STRING); + zpl_opts_add(&opts, "port", "port", "port number", ZPL_OPTS_INT); + + uint32_t ok = zpl_opts_compile(&opts, argc, argv); + + if (!ok) { + zpl_opts_print_errors(&opts); + zpl_opts_print_help(&opts); + return -1; + } + + int8_t is_viewer_only = zpl_opts_has_arg(&opts, "viewer-only"); + int8_t is_server_only = zpl_opts_has_arg(&opts, "server-only"); + int32_t seed = (int32_t)zpl_opts_integer(&opts, "seed", DEFAULT_WORLD_SEED); + uint16_t world_size = (uint16_t)zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE); + uint16_t chunk_size = DEFAULT_CHUNK_SIZE; //zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE); + zpl_string host = zpl_opts_string(&opts, "host", NULL); + uint16_t port = (uint16_t)zpl_opts_integer(&opts, "port", 0); + + game_kind play_mode = GAMEKIND_SINGLE; + + if (is_viewer_only) play_mode = GAMEKIND_CLIENT; + if (is_server_only) play_mode = GAMEKIND_HEADLESS; + + if (zpl_opts_has_arg(&opts, "random-seed")) { + zpl_random rnd={0}; + zpl_random_init(&rnd); + seed = zpl_random_gen_u32(&rnd); + zpl_printf("Seed: %u\n", seed); + } + + if (zpl_opts_has_arg(&opts, "preview-map")) { + generate_minimap(seed, WORLD_BLOCK_SIZE, chunk_size, world_size); + return 0; + } + + sighandler_register(); + game_init(host, port, play_mode, 1, seed, chunk_size, world_size, 0); + game_setup_ecs(); + game_run(); + + game_shutdown(); + sighandler_unregister(); + + zpl_string_free(host); + zpl_opts_free(&opts); + return 0; +} diff --git a/foundation.md b/foundation.md new file mode 100644 index 0000000..4f9f0dd --- /dev/null +++ b/foundation.md @@ -0,0 +1,64 @@ +foundation: + * platform + * viewer system ?? + * camera + * game + * debug ui + * packet utils + * arch + * input + * profiler + * renderer + * signal handling + * zpl options + * gen/textgen -> assets + * items + * inventory + * crafting + * notifications + * tooltips + * chunk + * blocks + * tiles (and chunk baker) + * systems (core systems) + * components + * net + * packets (but add custom messaging, and security) + * compression + * world + * wrold_view + * entity_view + + +------- +app - thing that runs game +game - the game stuff, includes client and server +packet - structure that has data written/read by client/server +asset - structure that describes tile/block/object/entity, something that can be visualized +module - a thing that uses a set of ecs components and systems to create a self-contained ecs module +------------ +world - a map of chunks within the game world +world-view - a representation of the world recreated by the client +---------- +tile - basic thing that makes up the chunks +block - 2nd level of things that make up the chunk +chunk - entity that contains set of tiles and blocks +object - an grid-independant static entity that can exist in the world +entity - a dynamic object that can change position within the world +item - an entity in the world, that can have a different state when its picked up + + +zpl.eco + foundation + sandbox + survival + +prefix: efd_ + + +entity + * objects + * players + * nps + * vehicles + * items