new iteration of draft

efd/v1
Vladyslav Hrytsenko 2023-03-12 14:19:59 +02:00
parent ac6b44eb0a
commit b032db0acd
2 changed files with 198 additions and 122 deletions

View File

@ -10,6 +10,7 @@ typedef int efd_app;
typedef uint16_t efd_entity_type; typedef uint16_t efd_entity_type;
typedef int32_t efd_result; typedef int32_t efd_result;
typedef void * efd_world; typedef void * efd_world;
typedef int efd_entid;
// define amount of memeory reserved for??? // define amount of memeory reserved for???
// custom data within COMMAND (cli->ser) and SNAPSHOT (ser->cli) // custom data within COMMAND (cli->ser) and SNAPSHOT (ser->cli)
@ -21,46 +22,70 @@ typedef void * efd_world;
#define EFD_TYPE(id) ((id - 1) >> EFD_TYPE_SHIFT) #define EFD_TYPE(id) ((id - 1) >> EFD_TYPE_SHIFT)
#define EFD_END 0 #define EFD_END 0
typedef enum efd_asset_type { typedef enum efd_instance_type {
EFD_NONE = 0, EFD_TYPE_NONE = 0,
EFD_TEXTURE,
EFD_TEXTURE_ATLAS,
EFD_ANIMATION,
EFD_SOUND,
EFD_FONT,
EFD_SHADER,
} efd_asset_type;
typedef enum efd_object_type { /* chunk */
EFD_TYPE_NONE,
EFD_TYPE_TILE, EFD_TYPE_TILE,
EFD_TYPE_BLOCK, EFD_TYPE_BLOCK,
EFD_TYPE_ENTITY,
EFD_TYPE_ITEM,
EFD_TYPE_CRAFT,
EFD_TYPE_CHUNK, EFD_TYPE_CHUNK,
EFD_TYPE_TYPE_LAST, /* entities */
EFD_TYPE_TYPE_MAX = 0xFFFF, EFD_TYPE_ITEM,
} efd_object_type; EFD_TYPE_OBJECT,
EFD_TYPE_DEVICE,
EFD_TYPE_VEHICLE,
EFD_TYPE_MOB,
EFD_TYPE_PLAYER,
/* other */
EFD_TYPE_OTHER,
/* utils */
EFD_TYPE_LAST,
EFD_TYPE_MAX = 0xFFFF,
} efd_instance_type;
typedef enum efd_flags { typedef enum efd_flags {
EFD_FLAG_COLLISION = (1 << 1), EFD_FLAG_COLLISION = (1 << 1),
EFD_FLAG_HAZARD = (1 << 2), EFD_FLAG_HAZARD = (1 << 2),
EFD_FLAG_ESSENTIAL = (1 << 3), EFD_FLAG_ESSENTIAL = (1 << 3),
EFD_FLAG_DESTROY_ON_COLLISION = (1 << 4), EFD_FLAG_DESTROY_ON_COLLISION = (1 << 4),
EFD_FLAG_AI = (1 << 5),
EFD_FLAG_PLAYER = (1 << 6),
EFD_FLAG_VEHICLE = (1 << 7),
} efd_flags; } efd_flags;
// assets
typedef enum efd_asset_type {
EFD_NONE = 0,
EFD_TEXTURE,
EFD_ANIMATION,
EFD_SOUND,
EFD_FONT,
EFD_SHADER,
} efd_asset_type;
typedef enum efd_asset_flags {
EFD_FLAG_ATLAS = (1 << 1), // texture is an atlas and has multiple frames
EFD_FLAG_LOOPED = (1 << 2), // frames are looped sequentially (requrires EFD_FLAG_ATLAS, can be combined with EFD_FLAG_RANDOM)
EFD_FLAG_RANDOM = (1 << 3), // one of the frames is randomly chosen (requrires EFD_FLAG_ATLAS, can be combined with EFD_FLAG_LOOPED)
EFD_FLAG_COMPLEX = (1 << 4), // frames have a complex state system and require a separate asset with EFD_ANIMATION type
} efd_asset_flags;
typedef struct efd_asset { typedef struct efd_asset {
efd_asset_type type; efd_asset_type type;
int id; int id;
const char *path; const char *path;
void *data; /* TODO: make a union */ int32_t flags;
struct {
int size_x;
int size_y;
} atlas;
void *data;
} efd_asset; } efd_asset;
// objects
typedef struct efd_tile { typedef struct efd_tile {
int id; int id;
int flags; int flags;
@ -76,27 +101,16 @@ typedef struct efd_block {
int vely; int vely;
} efd_block; } efd_block;
typedef struct efd_entity { typedef struct efd_item_list {
int id;
int flags;
} efd_entity;
typedef struct efd_item {
int id;
const char *t1;
const char *t2;
} efd_item;
typedef struct efd_craft_item {
int id; int id;
int qty; int qty;
} efd_craft_item; } efd_item_list;
typedef struct efd_craft { typedef struct efd_craft {
int producer; int producer;
int ticks; int ticks;
efd_craft_item *input; efd_item_list *input;
efd_craft_item *output; efd_item_list *output;
} efd_craft; } efd_craft;
typedef struct efd_tooltip { typedef struct efd_tooltip {
@ -104,6 +118,19 @@ typedef struct efd_tooltip {
const char *description; const char *description;
} efd_tooltip; } efd_tooltip;
typedef struct efd_entity {
int id;
int flags;
int stack;
union {
int durability;
int health;
};
efd_result (*spawn_cb)(efd_entid);
efd_item_list *drop;
} efd_entity;
typedef struct efd_app_desc { typedef struct efd_app_desc {
const char *name; const char *name;
int debug_ui; int debug_ui;
@ -123,8 +150,8 @@ typedef struct efd_app_desc {
efd_result (*system_cb)(); efd_result (*system_cb)();
efd_result (*update_cb)(); efd_result (*update_cb)();
efd_result (*render_cb)(efd_entity_type type); efd_result (*render_cb)(efd_entity_type type);
efd_result (*player_join_cb)(efd_entity player_id); efd_result (*player_join_cb)(efd_entid player_id);
efd_result (*player_leave_cb)(efd_entity player_id); efd_result (*player_leave_cb)(efd_entid player_id);
efd_result (*cleanup_cb)(); efd_result (*cleanup_cb)();
struct { struct {
@ -139,7 +166,6 @@ typedef struct efd_app_desc {
efd_tile *tiles; efd_tile *tiles;
efd_block *blocks; efd_block *blocks;
efd_entity *entities; efd_entity *entities;
efd_item *items;
efd_craft *crafting; efd_craft *crafting;
efd_tooltip *tooltips; efd_tooltip *tooltips;
} efd_app_desc; } efd_app_desc;
@ -155,64 +181,50 @@ enum {
TILE_WATER, TILE_WATER,
TILE_LAVA, TILE_LAVA,
BLOCK_STONE = EFD_ID(EFD_TYPE_BLOCK), BLOCK_AIR = EFD_ID(EFD_TYPE_BLOCK),
BLOCK_BRICK, BLOCK_WOOD,
BLOCK_HILL, BLOCK_HILL,
BLOCK_HILL_SNOW, BLOCK_HILL_SNOW,
BLOCK_FENCE, BLOCK_FENCE_LEFT,
BLOCK_WOOD, BLOCK_FENCE_RIGHT,
BLOCK_WALL, BLOCK_FENCE_UP,
BLOCK_FENCE_DOWN,
BLOCK_WALL_LEFT,
BLOCK_WALL_RIGHT,
BLOCK_WALL_UP,
BLOCK_WALL_DOWN,
BLOCK_BELT_LEFT, BLOCK_BELT_LEFT,
BLOCK_BELT_RIGHT, BLOCK_BELT_RIGHT,
BLOCK_BELT_UP, BLOCK_BELT_UP,
BLOCK_BELT_DOWN, BLOCK_BELT_DOWN,
ENTITY_PLAYER = EFD_ID(EFD_TYPE_ENTITY), ENTITY_IRON_ORE = EFD_ID(EFD_TYPE_ITEM),
ENTITY_MONSTER, ENTITY_IRON_INGOT,
ENTITY_TRUCK, ENTITY_IRON_PLATE,
ENTITY_TREE, ENTITY_SCREW,
ENTITY_CHEST, ENTITY_BELT,
ENTITY_FIR_TREE = EFD_ID(EFD_TYPE_OBJECT),
ENTITY_OAK_TREE,
ENTITY_CHEST = EFD_ID(EFD_TYPE_DEVICE),
ENTITY_FURNACE, ENTITY_FURNACE,
ENTITY_CRAFTBENCH, ENTITY_CRAFTBENCH,
ENTITY_ASSEMBLER, ENTITY_ASSEMBLER,
ITEM_IRON_ORE = EFD_ID(EFD_TYPE_ITEM), ENTITY_MONSTER = EFD_ID(EFD_TYPE_MOB),
ITEM_IRON_INGOT, ENTITY_RABBIT,
ITEM_IRON_PLATE, ENTITY_BOAR,
ITEM_SCREW, ENTITY_BIZON,
ITEM_BELT, ENTITY_BEAR,
ENTITY_TRUCK = EFD_ID(EFD_TYPE_VEHICLE),
ENTITY_CAR,
ENTITY_PLAYER = EFD_ID(EFD_TYPE_PLAYER),
}; };
// 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() { efd_result init() {
// NOTE: control sets could be implemented later on
// // 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);
// // 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);
// // 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; return 0;
} }
@ -228,7 +240,7 @@ efd_result update() {
efd_result render(efd_entity_type type) { efd_result render(efd_entity_type type) {
// switch (type) { // switch (type) {
// case EFD_ENTITY_PLAYER: // case ENTITY_PLAYER:
// /* additional/replacable rendering code on top of what EFD provides for built-in types */ // /* additional/replacable rendering code on top of what EFD provides for built-in types */
// efd_render_texture(ENTITY_PLAYER, 0, 0, 0, 0, 0, 0, 0, 0); // efd_render_texture(ENTITY_PLAYER, 0, 0, 0, 0, 0, 0, 0, 0);
@ -248,12 +260,12 @@ efd_result render(efd_entity_type type) {
return 0; return 0;
} }
efd_result player_join(efd_entity player) { efd_result player_join(efd_entid player) {
// efd_notify_push(player, "Test", "Welcome to the game!", 5.0f); // efd_notify_push(player, "Test", "Welcome to the game!", 5.0f);
return 0; return 0;
} }
efd_result player_leave(efd_entity player) { efd_result player_leave(efd_entid player) {
return 0; return 0;
} }
@ -261,6 +273,14 @@ efd_result cleanup() {
return 0; return 0;
} }
efd_result chest_spawn(efd_entid id) {
return 0;
}
efd_result furnace_spawn(efd_entid id) {
return 0;
}
efd_app_desc efd_main() { efd_app_desc efd_main() {
return (efd_app_desc){ return (efd_app_desc){
.name = "Survival", .name = "Survival",
@ -297,13 +317,24 @@ efd_app_desc efd_main() {
}, },
.assets = (efd_asset[]){ .assets = (efd_asset[]){
{EFD_TEXTURE, ENTITY_TREE, "assets/tree.png"}, {EFD_TEXTURE, TILE_GRASS, "assets/grass.png", EFD_FLAG_ATLAS | EFD_FLAG_RANDOM, .atlas = {4, 1}},
{EFD_TEXTURE, TILE_DIRT, "assets/dirt.png", EFD_FLAG_ATLAS | EFD_FLAG_RANDOM, .atlas = {4, 1}},
{EFD_TEXTURE, TILE_LAVA, "assets/lava.png", EFD_FLAG_ATLAS | EFD_FLAG_LOOPED, .atlas = {4, 1}},
{EFD_TEXTURE, TILE_WATER, "assets/water.png", EFD_FLAG_ATLAS | EFD_FLAG_RANDOM | EFD_FLAG_LOOPED, .atlas = {4, 1}},
{EFD_TEXTURE, ENTITY_OAK_TREE, "assets/tree.png"},
{EFD_TEXTURE, ENTITY_CHEST, "assets/chest.png"}, {EFD_TEXTURE, ENTITY_CHEST, "assets/chest.png"},
{EFD_TEXTURE, ENTITY_FURNACE, "assets/furnace.png"}, {EFD_TEXTURE, ENTITY_FURNACE, "assets/furnace.png"},
{EFD_TEXTURE, ENTITY_PLAYER, "assets/player.png"}, {EFD_TEXTURE, ENTITY_PLAYER, "assets/player.png", EFD_FLAG_ATLAS | EFD_FLAG_COMPLEX},
{EFD_TEXTURE, ENTITY_MONSTER, "assets/monster.png"}, {EFD_TEXTURE, ENTITY_MONSTER, "assets/monster.png"},
/* animations */
{EFD_ANIMATION, ENTITY_PLAYER, "assets/player.anim"},
/* sounds */
{EFD_SOUND, ENTITY_PLAYER, "assets/player.wav"},
{EFD_END}, {EFD_END},
}, },
@ -318,12 +349,21 @@ efd_app_desc efd_main() {
}, },
.blocks = (efd_block[]){ .blocks = (efd_block[]){
{BLOCK_WALL, EFD_FLAG_COLLISION, .bounce = 1.0f}, {BLOCK_AIR},
{BLOCK_HILL, EFD_FLAG_COLLISION}, {BLOCK_HILL, EFD_FLAG_COLLISION},
{BLOCK_HILL_SNOW, EFD_FLAG_COLLISION}, {BLOCK_HILL_SNOW, EFD_FLAG_COLLISION},
{BLOCK_FENCE, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_WOOD, EFD_FLAG_COLLISION, .bounce = 0.0f}, {BLOCK_WOOD, EFD_FLAG_COLLISION, .bounce = 0.0f},
{BLOCK_WALL_LEFT, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_WALL_RIGHT, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_WALL_UP, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_WALL_DOWN, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_FENCE_LEFT, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_FENCE_RIGHT, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_FENCE_UP, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_FENCE_DOWN, EFD_FLAG_COLLISION, .bounce = 1.0f},
{BLOCK_BELT_LEFT, .velx = -150.0f}, {BLOCK_BELT_LEFT, .velx = -150.0f},
{BLOCK_BELT_RIGHT, .velx = 150.0f}, {BLOCK_BELT_RIGHT, .velx = 150.0f},
{BLOCK_BELT_UP, .vely = -150.0f}, {BLOCK_BELT_UP, .vely = -150.0f},
@ -333,20 +373,22 @@ efd_app_desc efd_main() {
}, },
.entities = (efd_entity[]){ .entities = (efd_entity[]){
{ENTITY_TREE, EFD_FLAG_DESTROY_ON_COLLISION}, {ENTITY_IRON_ORE, .stack = 32},
{ENTITY_CHEST}, {ENTITY_IRON_PLATE, .stack = 32},
{ENTITY_FURNACE}, {ENTITY_SCREW, .stack = 256},
{ENTITY_PLAYER, EFD_FLAG_PLAYER}, {ENTITY_OAK_TREE, EFD_FLAG_DESTROY_ON_COLLISION, .drop = (efd_item_list[]){
{ENTITY_TRUCK, EFD_FLAG_VEHICLE}, {ENTITY_SCREW, 1},
{ENTITY_MONSTER, EFD_FLAG_AI}, {EFD_END},
}},
{EFD_END}, {ENTITY_CHEST, .spawn_cb = chest_spawn},
}, {ENTITY_FURNACE, .spawn_cb = furnace_spawn},
{ENTITY_MONSTER, .health = 256},
{ENTITY_TRUCK},
{ENTITY_PLAYER},
.items = (efd_item[]){
// {ITEM_WOOD, "Wood", "A piece of wood."},
// {ITEM_STONE, "Stone", "A piece of stone."},
{EFD_END}, {EFD_END},
}, },
@ -354,38 +396,37 @@ efd_app_desc efd_main() {
{ {
.producer = ENTITY_FURNACE, .producer = ENTITY_FURNACE,
.ticks = 20, .ticks = 20,
.input = (efd_craft_item[]){ .input = (efd_item_list[]){
{ITEM_IRON_ORE, 1}, {ENTITY_IRON_ORE, 1},
{EFD_END}, {EFD_END},
}, },
.output = (efd_craft_item[]){ .output = (efd_item_list[]){
{ITEM_IRON_PLATE, 4}, {ENTITY_IRON_PLATE, 4},
{EFD_END}, {EFD_END},
}, },
}, },
{ {
.producer = ENTITY_CRAFTBENCH, .producer = ENTITY_CRAFTBENCH,
.ticks = 40, .ticks = 40,
.input = (efd_craft_item[]){ .input = (efd_item_list[]){
{ITEM_IRON_PLATE, 1}, {ENTITY_IRON_PLATE, 1},
{EFD_END}, {EFD_END},
}, },
.output = (efd_craft_item[]){ .output = (efd_item_list[]){
{ITEM_SCREW, 8}, {ENTITY_SCREW, 8},
{EFD_END}, {EFD_END},
}, },
}, },
{ {
.producer = ENTITY_ASSEMBLER, .producer = ENTITY_ASSEMBLER,
.ticks = 120, .ticks = 120,
.input = (efd_craft_item[]){ .input = (efd_item_list[]){
{BLOCK_FENCE, 1}, {ENTITY_SCREW, 4},
{ITEM_SCREW, 4}, {ENTITY_IRON_PLATE, 2},
{ITEM_IRON_PLATE, 2},
{EFD_END}, {EFD_END},
}, },
.output = (efd_craft_item[]){ .output = (efd_item_list[]){
{ITEM_BELT, 1}, {ENTITY_BELT, 1},
{EFD_END}, {EFD_END},
}, },
}, },
@ -412,8 +453,8 @@ int main(int argc, char **argv) {
printf("value: %f\n", desc.rules.item_pickup_radius); printf("value: %f\n", desc.rules.item_pickup_radius);
printf("TILE_DIRT: %d\n", TILE_DIRT); printf("TILE_DIRT: %d\n", TILE_DIRT);
printf("TILE_GRASS: %d\n", TILE_GRASS); printf("TILE_GRASS: %d\n", TILE_GRASS);
printf("ENTITY_PLAYER: %d\n", ENTITY_PLAYER); printf("ENTITY_PLAYER: %d, is_valid type: %d\n", ENTITY_PLAYER, EFD_TYPE(ENTITY_PLAYER) == EFD_TYPE_PLAYER);
printf("ENTITY_CHEST: %d\n", ENTITY_CHEST); printf("ENTITY_CHEST: %d, is_valid type: %d\n", ENTITY_CHEST, EFD_TYPE(ENTITY_CHEST) == EFD_TYPE_DEVICE);
desc.init_cb(); desc.init_cb();

View File

@ -45,8 +45,14 @@
* tile - basic thing that makes up the chunks * tile - basic thing that makes up the chunks
* block - 2nd level of things that make up the chunk * block - 2nd level of things that make up the chunk
* entity - an grid-independant static or dynamic entity that can exist in the world and has some systems controlling it * entity - an grid-independant static or dynamic entity that can exist in the world and has some systems controlling it
* item - an entity in the world, that can have a different state when its picked up primary archetypes:
* crafting - a recipe that can be used to craft an item * item - an entity in the world, that can have a different state when its picked up
* object - an item that can be placed in the world
* device - an object that can be interacted with
* mob - an entity that can be controlled by ai
* player - an entity that can be controlled by a player
* vehicle - an entity that can be used to transport other entities
* craft - a recipe that can be used to craft an item
## Naming ## Naming
@ -57,16 +63,27 @@
* survival * survival
* prefix: efd_ * prefix: efd_
## Objects ## Concepts
* tile * tile
* block * block
* entity * entity
* npc * item
* object
* device
* mob
* player * player
* vehicle * vehicle
* item
* craft * craft
## Transitions
* item -> tile (item destroyed, tile replaced)
* item -> block (item destroyed, block created)
* item -> entity (item hidden and untracked, entity component added) // item becomes entity, just changes state
* item -> item (crafting) (item destroyed, item created)
* tile -> item (tile replaced, item created)
* block -> item (block destroyed, item created)
* block -> block (crafting) (block destroyed, block created)
* entity -> item (entity component removed, item shown and tracked) // entity becomes item, just changes state
## Features ## Features
* In-memory lists * In-memory lists
@ -76,3 +93,21 @@
* prafabs for entities (pipeline for entities) * prafabs for entities (pipeline for entities)
* built in server->client RPC * built in server->client RPC
* *
// // 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);
// // 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);
// // 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);