From dde805203b320dd008718099b965f7275c04d1cd Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 19 Apr 2022 23:30:07 +0200 Subject: [PATCH] Add items --- deps/protogen | 2 +- meshes/axe.gox | Bin 0 -> 6397 bytes meshes/axe.txt | 39 ++ meshes/pickaxe.gox | Bin 0 -> 5205 bytes meshes/pickaxe.txt | 31 ++ meshes/unknown.gox | Bin 0 -> 5811 bytes meshes/unknown.txt | 732 +++++++++++++++++++++++++++++++ models/player.txt | 34 +- shaders/3d/entity/fragment.glsl | 1 - shaders/3d/entity/vertex.glsl | 7 +- shaders/3d/item/fragment.glsl | 16 + shaders/3d/item/vertex.glsl | 25 ++ shaders/3d/terrain/fragment.glsl | 1 - shaders/3d/terrain/vertex.glsl | 7 +- src/CMakeLists.txt | 4 + src/client/camera.c | 7 +- src/client/camera.h | 4 +- src/client/client.c | 2 + src/client/client_entity.c | 10 +- src/client/client_entity.h | 10 +- src/client/client_inventory.c | 109 +++++ src/client/client_inventory.h | 16 + src/client/client_item.c | 43 ++ src/client/client_item.h | 18 + src/client/client_node.c | 22 +- src/client/client_node.h | 5 +- src/client/client_player.c | 79 ++-- src/client/client_player.h | 21 +- src/client/client_terrain.c | 2 +- src/client/debug_menu.c | 20 +- src/client/debug_menu.h | 1 + src/client/game.c | 110 +---- src/client/game.h | 3 +- src/client/gui.c | 2 +- src/client/gui.h | 6 +- src/client/input.c | 10 +- src/client/interact.c | 46 +- src/client/interact.h | 6 + src/client/mesh.c | 125 ++++++ src/client/mesh.h | 1 + src/client/model.c | 18 +- src/client/model.h | 3 +- src/client/raycast.c | 2 +- src/client/screenshot.c | 73 +++ src/client/screenshot.h | 6 + src/client/shader.c | 16 +- src/client/shader.h | 2 +- src/client/terrain_gfx.c | 6 +- src/client/window.h | 3 + src/item.c | 98 +++++ src/item.h | 40 ++ src/node.c | 2 +- src/node.h | 6 +- src/physics.c | 2 +- src/server/server.c | 5 +- src/server/server_player.c | 48 +- src/server/server_player.h | 7 + src/server/server_terrain.c | 2 +- src/server/terrain_gen.c | 2 +- src/server/trees.c | 2 +- src/server/trees.h | 2 +- src/terrain.c | 6 +- src/types.def | 10 + 63 files changed, 1696 insertions(+), 242 deletions(-) create mode 100644 meshes/axe.gox create mode 100644 meshes/axe.txt create mode 100644 meshes/pickaxe.gox create mode 100644 meshes/pickaxe.txt create mode 100644 meshes/unknown.gox create mode 100644 meshes/unknown.txt create mode 100755 shaders/3d/item/fragment.glsl create mode 100755 shaders/3d/item/vertex.glsl create mode 100644 src/client/client_inventory.c create mode 100644 src/client/client_inventory.h create mode 100644 src/client/client_item.c create mode 100644 src/client/client_item.h create mode 100644 src/client/screenshot.c create mode 100644 src/client/screenshot.h create mode 100644 src/item.c create mode 100644 src/item.h diff --git a/deps/protogen b/deps/protogen index 45b6912..97963be 160000 --- a/deps/protogen +++ b/deps/protogen @@ -1 +1 @@ -Subproject commit 45b691209c95e5a758536a32564c329683550dca +Subproject commit 97963be1d8fbc53dce1b116f1d62340dee83383c diff --git a/meshes/axe.gox b/meshes/axe.gox new file mode 100644 index 0000000000000000000000000000000000000000..08bb09adcbc34141b7e9670c2635e70f504814e9 GIT binary patch literal 6397 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 literal 0 HcmV?d00001 diff --git a/meshes/pickaxe.txt b/meshes/pickaxe.txt new file mode 100644 index 0000000..c14d78e --- /dev/null +++ b/meshes/pickaxe.txt @@ -0,0 +1,31 @@ +# Goxel 0.10.6 +# One line per voxel +# X Y Z RRGGBB +0 -4 7 a0a0a0 +0 -4 8 a0a0a0 +0 -3 8 999999 +0 -3 9 a0a0a0 +0 -2 9 a0a0a0 +0 -1 9 8b8b8b +0 -2 10 a0a0a0 +0 -1 10 a9a9a9 +0 0 0 503612 +0 0 1 503612 +0 0 2 584120 +0 0 3 43351e +0 0 4 503612 +0 0 5 503612 +0 0 6 4a3312 +0 0 7 5c421a +0 4 7 999999 +0 0 8 5a380e +0 3 8 999999 +0 4 8 a0a0a0 +0 0 9 a0a0a0 +0 1 9 a9a9a9 +0 2 9 a0a0a0 +0 3 9 a0a0a0 +0 0 10 a9a9a9 +0 1 10 8b8b8b +0 2 10 a0a0a0 +0 0 11 a0a0a0 diff --git a/meshes/unknown.gox b/meshes/unknown.gox new file mode 100644 index 0000000000000000000000000000000000000000..61584af4c303ed37841d9b3f5ad7c38f3c8288ff GIT binary patch literal 5811 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 #include "client/camera.h" -#include "client/client.h" struct Camera camera; @@ -14,6 +13,12 @@ static void camera_update() mat4x4_look_at(camera.view, camera.eye, center, camera.up); } +void camera_init() +{ + camera_set_position((v3f32) {0.0f, 0.0f, 0.0f}); + camera_set_angle(0.0f, 0.0f); +} + void camera_set_position(v3f32 pos) { camera.eye[0] = pos.x; diff --git a/src/client/camera.h b/src/client/camera.h index abe7d8f..3e3d517 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -1,8 +1,6 @@ #ifndef _CAMERA_H_ #define _CAMERA_H_ -#include -#include #include #include "types.h" @@ -16,8 +14,8 @@ extern struct Camera { } movement_dirs; } camera; +void camera_init(); void camera_set_position(v3f32 pos); void camera_set_angle(f32 yaw, f32 pitch); -void camera_on_resize(int width, int height); #endif // _CAMERA_H_ diff --git a/src/client/client.c b/src/client/client.c index 5393922..40f58dc 100644 --- a/src/client/client.c +++ b/src/client/client.c @@ -7,6 +7,7 @@ #include #include "client/client.h" #include "client/client_auth.h" +#include "client/client_inventory.h" #include "client/client_player.h" #include "client/client_terrain.h" #include "client/debug_menu.h" @@ -143,6 +144,7 @@ int main(int argc, char **argv) client->on_recv_type[DRAGONNET_TYPE_ToClientEntityRemove ] = (void *) &client_entity_remove; client->on_recv_type[DRAGONNET_TYPE_ToClientEntityUpdatePosRot ] = (void *) &client_entity_update_pos_rot; client->on_recv_type[DRAGONNET_TYPE_ToClientEntityUpdateNametag] = (void *) &client_entity_update_nametag; + client->on_recv_type[DRAGONNET_TYPE_ToClientPlayerInventory ] = (void *) &client_inventory_update_player; flag_ini(&finish); flag_ini(&gfx_init); diff --git a/src/client/client_entity.c b/src/client/client_entity.c index 97173e8..2bc3253 100644 --- a/src/client/client_entity.c +++ b/src/client/client_entity.c @@ -94,7 +94,7 @@ static void update_nametag(ClientEntity *entity) if (!entity->data.nametag) entity->nametag->visible = false; } else if (entity->data.nametag) { - entity->nametag = gui_add(NULL, (GUIElementDefinition) { + entity->nametag = gui_add(NULL, (GUIElementDef) { .pos = {-1.0f, -1.0f}, .z_index = 0.1f, .offset = {0, 0}, @@ -233,7 +233,7 @@ void client_entity_transform(ClientEntity *entity) model_node_transform(entity->model->root); } -void client_entity_add(__attribute__((unused)) DragonnetPeer *peer, ToClientEntityAdd *pkt) +void client_entity_add(__attribute__((unused)) void *peer, ToClientEntityAdd *pkt) { if (pkt->type >= COUNT_ENTITY) return; @@ -264,12 +264,12 @@ void client_entity_add(__attribute__((unused)) DragonnetPeer *peer, ToClientEnti refcount_drp(&entity->rc); } -void client_entity_remove(__attribute__((unused)) DragonnetPeer *peer, ToClientEntityRemove *pkt) +void client_entity_remove(__attribute__((unused)) void *peer, ToClientEntityRemove *pkt) { map_del(&entities, &pkt->id, &cmp_entity, &entity_drop, NULL, &refcount_obj); } -void client_entity_update_pos_rot(__attribute__((unused)) DragonnetPeer *peer, ToClientEntityUpdatePosRot *pkt) +void client_entity_update_pos_rot(__attribute__((unused)) void *peer, ToClientEntityUpdatePosRot *pkt) { ClientEntity *entity = client_entity_grab(pkt->id); @@ -291,7 +291,7 @@ void client_entity_update_pos_rot(__attribute__((unused)) DragonnetPeer *peer, T refcount_drp(&entity->rc); } -void client_entity_update_nametag(__attribute__((unused)) DragonnetPeer *peer, ToClientEntityUpdateNametag *pkt) +void client_entity_update_nametag(__attribute__((unused)) void *peer, ToClientEntityUpdateNametag *pkt) { ClientEntity *entity = client_entity_grab(pkt->id); diff --git a/src/client/client_entity.h b/src/client/client_entity.h index 53125db..03238a6 100644 --- a/src/client/client_entity.h +++ b/src/client/client_entity.h @@ -1,12 +1,12 @@ #ifndef _CLIENT_ENTITY_H_ #define _CLIENT_ENTITY_H_ -#include #include #include #include "client/gui.h" #include "client/model.h" #include "entity.h" +#include "item.h" #include "types.h" typedef struct { @@ -56,9 +56,9 @@ void client_entity_drop(ClientEntity *entity); void client_entity_transform(ClientEntity *entity); -void client_entity_add(DragonnetPeer *peer, ToClientEntityAdd *pkt); -void client_entity_remove(DragonnetPeer *peer, ToClientEntityRemove *pkt); -void client_entity_update_pos_rot(DragonnetPeer *peer, ToClientEntityUpdatePosRot *pkt); -void client_entity_update_nametag(DragonnetPeer *peer, ToClientEntityUpdateNametag *pkt); +void client_entity_add(void *peer, ToClientEntityAdd *pkt); +void client_entity_remove(void *peer, ToClientEntityRemove *pkt); +void client_entity_update_pos_rot(void *peer, ToClientEntityUpdatePosRot *pkt); +void client_entity_update_nametag(void *peer, ToClientEntityUpdateNametag *pkt); #endif // _CLIENT_ENTITY_H_ diff --git a/src/client/client_inventory.c b/src/client/client_inventory.c new file mode 100644 index 0000000..4ae916b --- /dev/null +++ b/src/client/client_inventory.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include "client/client_config.h" +#include "client/client_inventory.h" +#include "client/client_item.h" +#include "client/gl_debug.h" +#include "client/frustum.h" +#include "client/light.h" +#include "client/shader.h" + +static GLuint _3d_shader_prog; +static GLint _3d_loc_VP; +static ModelShader _3d_model_shader; +static LightShader _3d_light_shader; + +bool client_inventory_init() +{ + char *_3d_shader_defs; + asprintf(&_3d_shader_defs, "#define VIEW_DISTANCE %lf\n", client_config.view_distance); + + if (!shader_program_create(RESSOURCE_PATH "shaders/3d/item", &_3d_shader_prog, _3d_shader_defs)) { + fprintf(stderr, "[error] failed to create 3D item shader program\n"); + return false; + } + + free(_3d_shader_defs); + + _3d_loc_VP = glGetUniformLocation(_3d_shader_prog, "VP"); + + _3d_model_shader.prog = _3d_shader_prog; + _3d_model_shader.loc_transform = glGetUniformLocation(_3d_shader_prog, "model"); GL_DEBUG + + _3d_light_shader.prog = _3d_shader_prog; + light_shader_locate(&_3d_light_shader); + + return true; +} + +void client_inventory_deinit() +{ + glDeleteProgram(_3d_shader_prog); GL_DEBUG +} + +void client_inventory_update() +{ + glProgramUniformMatrix4fv(_3d_shader_prog, _3d_loc_VP, 1, GL_FALSE, frustum[0]); GL_DEBUG + light_shader_update(&_3d_light_shader); +} + +static void wield_init(ModelNode *hand) +{ + if (hand) + model_node_add_mesh(hand, &(ModelMesh) { + .mesh = NULL, + .textures = NULL, + .num_textures = 0, + .shader = &_3d_model_shader, + }); +} + +static void wield_update(ModelNode *hand, ModelNode *arm, ItemType item) +{ + Mesh *mesh = client_item_mesh(item); + + if (hand) + ((ModelMesh *) hand->meshes.ptr)[0].mesh = mesh; + + if (arm) { + arm->rot.x = mesh ? -M_PI / 8.0 : 0.0; + model_node_transform(arm); + } +} + +void client_inventory_init_player(ClientEntity *entity) +{ + ClientPlayerData *data = entity->extra; + + item_stack_initialize(&data->inventory.left); + item_stack_initialize(&data->inventory.right); + + wield_init(data->bones.hand_left); + wield_init(data->bones.hand_right); +} + +void client_inventory_deinit_player(ClientEntity *entity) +{ + ClientPlayerData *data = entity->extra; + + item_stack_destroy(&data->inventory.left); + item_stack_destroy(&data->inventory.right); +} + +void client_inventory_update_player(__attribute__((unused)) void *peer, ToClientPlayerInventory *pkt) +{ + ClientEntity *entity = client_player_entity(pkt->id); + if (!entity) + return; + + ClientPlayerData *data = entity->extra; + + item_stack_deserialize(&data->inventory.left, &pkt->left); + item_stack_deserialize(&data->inventory.right, &pkt->right); + + wield_update(data->bones.hand_left, data->bones.arm_left, data->inventory.left.type); + wield_update(data->bones.hand_right, data->bones.arm_right, data->inventory.right.type); + + refcount_drp(&entity->rc); +} diff --git a/src/client/client_inventory.h b/src/client/client_inventory.h new file mode 100644 index 0000000..3b09789 --- /dev/null +++ b/src/client/client_inventory.h @@ -0,0 +1,16 @@ +#ifndef _CLIENT_INVENTORY_H_ +#define _CLIENT_INVENTORY_H_ + +#include +#include "client/client_player.h" +#include "client/model.h" + +bool client_inventory_init(); +void client_inventory_deinit(); +void client_inventory_update(); + +void client_inventory_init_player(ClientEntity *entity); +void client_inventory_deinit_player(ClientEntity *entity); +void client_inventory_update_player(void *peer, ToClientPlayerInventory *pkt); + +#endif // _CLIENT_INVENTORY_H_ diff --git a/src/client/client_item.c b/src/client/client_item.c new file mode 100644 index 0000000..923fd74 --- /dev/null +++ b/src/client/client_item.c @@ -0,0 +1,43 @@ +#include "client/client_item.h" + +ClientItemDef client_item_defs[COUNT_ITEM] = { + // unknown + { + .mesh_path = RESSOURCE_PATH "meshes/unknown.txt", + .mesh = {0}, + }, + // none + { + .mesh_path = NULL, + .mesh = {0}, + }, + // pickaxe + { + .mesh_path = RESSOURCE_PATH "meshes/pickaxe.txt", + .mesh = {0}, + }, + // axe + { + .mesh_path = RESSOURCE_PATH "meshes/axe.txt", + .mesh = {0}, + }, +}; + +void client_item_init() +{ + for (ItemType i = 0; i < COUNT_ITEM; i++) + if (client_item_defs[i].mesh_path) + mesh_load(&client_item_defs[i].mesh, client_item_defs[i].mesh_path); +} + +void client_item_deinit() +{ + for (ItemType i = 0; i < COUNT_ITEM; i++) + if (client_item_defs[i].mesh_path) + mesh_destroy(&client_item_defs[i].mesh); +} + +Mesh *client_item_mesh(ItemType type) +{ + return client_item_defs[type].mesh_path ? &client_item_defs[type].mesh : NULL; +} diff --git a/src/client/client_item.h b/src/client/client_item.h new file mode 100644 index 0000000..0105abf --- /dev/null +++ b/src/client/client_item.h @@ -0,0 +1,18 @@ +#ifndef _CLIENT_ITEM_H_ +#define _CLIENT_ITEM_H_ + +#include "client/mesh.h" +#include "item.h" + +typedef struct { + const char *mesh_path; + Mesh mesh; +} ClientItemDef; + +extern ClientItemDef client_item_defs[]; + +void client_item_init(); +void client_item_deinit(); +Mesh *client_item_mesh(ItemType type); + +#endif // _CLIENT_ITEM_H_ diff --git a/src/client/client_node.c b/src/client/client_node.c index 956e18f..56c646e 100644 --- a/src/client/client_node.c +++ b/src/client/client_node.c @@ -38,7 +38,7 @@ static void render_color(NodeArgsRender *args) args->vertex.color = ((ColorData *) args->node->data)->color; } -ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { +ClientNodeDef client_node_defs[NODE_UNLOADED] = { // unknown { .tiles = TILES_SIMPLE(RESSOURCE_PATH "textures/unknown.png"), @@ -47,6 +47,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = NULL, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Unknown", }, // air { @@ -56,6 +57,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = NULL, .pointable = false, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Air", }, // grass { @@ -65,6 +67,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = &render_grass, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Grass", }, // dirt { @@ -74,6 +77,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = NULL, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Dirt", }, // stone { @@ -83,6 +87,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = &render_stone, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Stone", }, // snow { @@ -92,6 +97,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = NULL, .pointable = true, .selection_color = {0.1f, 0.5f, 1.0f}, + .name = "Snow", }, // oak wood { @@ -105,6 +111,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = &render_color, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Oak Wood", }, // oak leaves { @@ -114,6 +121,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = &render_color, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Oak Leaves", }, // pine wood { @@ -127,6 +135,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = &render_color, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Pine Wood", }, // pine leaves { @@ -136,6 +145,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = &render_color, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Pine Leaves", }, // palm wood { @@ -149,6 +159,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = &render_color, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Palm Wood", }, // palm leaves { @@ -158,6 +169,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = &render_color, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Palm Leaves", }, // sand { @@ -167,6 +179,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = NULL, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Sand", }, // water { @@ -176,6 +189,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = NULL, .pointable = false, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Water", }, // lava { @@ -185,6 +199,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = NULL, .pointable = false, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Lava", }, // vulcano_stone { @@ -194,13 +209,14 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = { .render = NULL, .pointable = true, .selection_color = {1.0f, 1.0f, 1.0f}, + .name = "Vulcano Stone", }, }; void client_node_init() { - for (NodeType node = NODE_UNKNOWN; node < NODE_UNLOADED; node++) { - ClientNodeDefinition *def = &client_node_definitions[node]; + for (NodeType node = 0; node < NODE_UNLOADED; node++) { + ClientNodeDef *def = &client_node_defs[node]; if (def->visibility != VISIBILITY_NONE) { Texture *textures[6]; diff --git a/src/client/client_node.h b/src/client/client_node.h index 7edcf66..57ae625 100644 --- a/src/client/client_node.h +++ b/src/client/client_node.h @@ -30,9 +30,10 @@ typedef struct { void (*render)(NodeArgsRender *args); bool pointable; v3f32 selection_color; -} ClientNodeDefinition; + char *name; +} ClientNodeDef; -extern ClientNodeDefinition client_node_definitions[]; +extern ClientNodeDef client_node_defs[]; void client_node_init(); #endif // _CLIENT_NODE_H_ diff --git a/src/client/client_player.c b/src/client/client_player.c index 326ab53..ccbd059 100644 --- a/src/client/client_player.c +++ b/src/client/client_player.c @@ -2,6 +2,7 @@ #include #include "client/camera.h" #include "client/client.h" +#include "client/client_inventory.h" #include "client/client_player.h" #include "client/client_terrain.h" #include "client/cube.h" @@ -10,16 +11,6 @@ #include "environment.h" #include "physics.h" -typedef struct { - ModelNode *nametag; - ModelNode *neck; - ModelNode *eyes; - ModelNode *shoulder_left; - ModelNode *shoulder_right; - ModelNode *hip_left; - ModelNode *hip_right; -} PlayerModelBones; - struct ClientPlayer client_player; static ClientEntity *player_entity; @@ -33,10 +24,10 @@ static void update_camera() { vec4 dst, src = {0.0f, 0.0f, 0.0f, 1.0f}; - PlayerModelBones *bones = player_entity->extra; + ClientPlayerData *data = player_entity->extra; - if (bones->eyes) - mat4x4_mul_vec4(dst, bones->eyes->abs, src); + if (data->bones.eyes) + mat4x4_mul_vec4(dst, data->bones.eyes->abs, src); else vec4_dup(dst, src); @@ -88,21 +79,26 @@ static void on_add(ClientEntity *entity) entity->model = model_clone(player_model); entity->model->extra = refcount_grb(&entity->rc); - PlayerModelBones *bones = entity->extra = malloc(sizeof *bones); - *bones = (PlayerModelBones) {NULL}; - model_get_bones(entity->model, (ModelBoneMapping[]) { - {"player.nametag", &bones->nametag }, - {"player.neck", &bones->neck }, - {"player.neck.head.eyes", &bones->eyes }, - {"player.body.upper.shoulders.left", &bones->shoulder_left }, - {"player.body.upper.shoulders.right", &bones->shoulder_right}, - {"player.body.lower.hips.left", &bones->hip_left }, - {"player.body.lower.hips.right", &bones->hip_right }, - }, 7); - - entity->nametag_offset = bones->nametag ? &bones->nametag->abs : NULL; + ClientPlayerData *data = entity->extra = malloc(sizeof *data); + data->bones = (struct ClientPlayerBones) {NULL}; + + model_get_bones(entity->model, (ModelBoneMapping[9]) { + {"nametag", &data->bones.nametag }, + {"neck", &data->bones.neck }, + {"neck.head.eyes", &data->bones.eyes }, + {"arm_left", &data->bones.arm_left }, + {"arm_right", &data->bones.arm_right }, + {"arm_left.hand", &data->bones.hand_left }, + {"arm_right.hand", &data->bones.hand_right}, + {"leg_left", &data->bones.leg_left }, + {"leg_right", &data->bones.leg_right }, + }, 9); + + entity->nametag_offset = data->bones.nametag ? &data->bones.nametag->abs : NULL; entity->box_collision = (aabb3f32) {{-0.45f, 0.0f, -0.45f}, {0.45f, 1.8f, 0.45f}}; + client_inventory_init_player(entity); + model_scene_add(entity->model); client_entity_transform(entity); } @@ -115,18 +111,19 @@ static void on_remove(ClientEntity *entity) static void on_free(ClientEntity *entity) { + client_inventory_init_player(entity); free(entity->extra); } static void on_transform(ClientEntity *entity) { - PlayerModelBones *bones = entity->extra; + ClientPlayerData *data = entity->extra; entity->model->root->rot.x = entity->model->root->rot.z = 0.0f; - if (bones->neck) { - bones->neck->rot.x = entity->data.rot.x; - model_node_transform(bones->neck); + if (data->bones.neck) { + data->bones.neck->rot.x = entity->data.rot.x; + model_node_transform(data->bones.neck); } } @@ -174,8 +171,8 @@ static void local_on_update_nametag(ClientEntity *entity) static void __attribute__((unused)) on_model_step(Model *model, __attribute__((unused)) f64 dtime) { - PlayerModelBones *bones = ((ClientEntity *) model->extra)->extra; - (void) bones; + ClientPlayerData *data = ((ClientEntity *) model->extra)->extra; + (void) data; // ToDo: animations } static void on_model_delete(Model *model) @@ -241,7 +238,19 @@ void client_player_gfx_deinit() model_delete(player_model); } -ClientEntity *client_player_entity() +ClientEntity *client_player_entity(u64 id) +{ + ClientEntity *entity = client_entity_grab(id); + + if (entity->type == &client_entity_types[ENTITY_LOCALPLAYER] + || entity->type == &client_entity_types[ENTITY_PLAYER]) + return entity; + + refcount_drp(&entity->rc); + return NULL; +} + +ClientEntity *client_player_entity_local() { ClientEntity *entity = NULL; @@ -280,7 +289,7 @@ void client_player_update_rot(ClientEntity *entity) // jump if possible void client_player_jump() { - ClientEntity *entity = client_player_entity(); + ClientEntity *entity = client_player_entity_local(); if (!entity) return; @@ -305,7 +314,7 @@ void client_player_jump() // to be called every frame void client_player_tick(f64 dtime) { - ClientEntity *entity = client_player_entity(); + ClientEntity *entity = client_player_entity_local(); if (!entity) return; diff --git a/src/client/client_player.h b/src/client/client_player.h index 5ddefa0..1028955 100644 --- a/src/client/client_player.h +++ b/src/client/client_player.h @@ -11,13 +11,32 @@ extern struct ClientPlayer { pthread_rwlock_t lock_movement; } client_player; +typedef struct { + struct { + ItemStack left; + ItemStack right; + } inventory; + struct ClientPlayerBones { + ModelNode *nametag; + ModelNode *neck; + ModelNode *eyes; + ModelNode *arm_left; + ModelNode *arm_right; + ModelNode *hand_left; + ModelNode *hand_right; + ModelNode *leg_left; + ModelNode *leg_right; + } bones; +} ClientPlayerData; + void client_player_init(); // called on startup void client_player_deinit(); // called on shutdown void client_player_gfx_init(); void client_player_gfx_deinit(); -ClientEntity *client_player_entity(); // grab and return client entity +ClientEntity *client_player_entity(u64 id); // grab and return client entity by id +ClientEntity *client_player_entity_local(); // grab and return local client entity void client_player_jump(); // jump if possible diff --git a/src/client/client_terrain.c b/src/client/client_terrain.c index c9c0ff1..148c084 100644 --- a/src/client/client_terrain.c +++ b/src/client/client_terrain.c @@ -63,7 +63,7 @@ static void sync_step() static size_t old_num_requests = 0; v3f64 player_pos; - ClientEntity *entity = client_player_entity(); + ClientEntity *entity = client_player_entity_local(); if (entity) { pthread_rwlock_rdlock(&entity->lock_pos_rot); diff --git a/src/client/debug_menu.c b/src/client/debug_menu.c index 8e60bdb..e3f1a9c 100644 --- a/src/client/debug_menu.c +++ b/src/client/debug_menu.c @@ -6,12 +6,14 @@ #include #include #include "client/client_config.h" +#include "client/client_node.h" #include "client/client_player.h" #include "client/client_terrain.h" #include "client/debug_menu.h" #include "client/game.h" #include "client/gl_debug.h" #include "client/gui.h" +#include "client/interact.h" #include "client/window.h" #include "day.h" #include "environment.h" @@ -23,7 +25,7 @@ static bool changed_elements[COUNT_ENTRY] = {false}; static pthread_mutex_t changed_elements_mtx = PTHREAD_MUTEX_INITIALIZER; static bool debug_menu_enabled = true; -static DebugMenuEntry last_always_visible = ENTRY_POS; +static DebugMenuEntry last_always_visible = ENTRY_POINTED; static char *get_entry_text(DebugMenuEntry entry) { @@ -33,6 +35,10 @@ static char *get_entry_text(DebugMenuEntry entry) int minutes = 0; v3f64 pos = {0.0f, 0.0f, 0.0f}; v3f32 rot = {0.0f, 0.0f, 0.0f}; + char *pnt_name = NULL; + + // shortcut + static struct InteractPointed *pnt = &interact_pointed; switch (entry) { case ENTRY_POS: @@ -40,7 +46,7 @@ static char *get_entry_text(DebugMenuEntry entry) case ENTRY_PITCH: case ENTRY_HUMIDITY: case ENTRY_TEMPERATURE: { - ClientEntity *entity = client_player_entity(); + ClientEntity *entity = client_player_entity_local(); if (!entity) return strdup(""); @@ -52,6 +58,13 @@ static char *get_entry_text(DebugMenuEntry entry) break; } + case ENTRY_POINTED: + if (!pnt->exists) + return strdup(""); + + pnt_name = client_node_defs[pnt->node].name; + break; + case ENTRY_FLIGHT: case ENTRY_COLLISION: pthread_rwlock_rdlock(&client_player.lock_movement); @@ -78,6 +91,7 @@ static char *get_entry_text(DebugMenuEntry entry) case ENTRY_VERSION: asprintf(&str, "Dragonblocks Alpha %s", VERSION ); break; case ENTRY_FPS: asprintf(&str, "%d FPS", game_fps ); break; case ENTRY_POS: asprintf(&str, "(%.1f %.1f %.1f)", pos.x, pos.y, pos.z ); break; + case ENTRY_POINTED: asprintf(&str, "%s (%d, %d, %d)", pnt_name, pnt->pos.x, pnt->pos.y, pnt->pos.z ); break; case ENTRY_YAW: asprintf(&str, "yaw = %.1f", 360.0 - rot.y / M_PI * 180.0 ); break; case ENTRY_PITCH: asprintf(&str, "pitch = %.1f", -rot.x / M_PI * 180.0 ); break; case ENTRY_TIME: asprintf(&str, "%02d:%02d", hours, minutes ); break; @@ -106,7 +120,7 @@ void debug_menu_init() s32 offset = -16; for (DebugMenuEntry i = 0; i < COUNT_ENTRY; i++) { - gui_elements[i] = gui_add(NULL, (GUIElementDefinition) { + gui_elements[i] = gui_add(NULL, (GUIElementDef) { .pos = {0.0f, 0.0f}, .z_index = 0.1f, .offset = {2, offset += 18}, diff --git a/src/client/debug_menu.h b/src/client/debug_menu.h index 3b1b7de..74f23ac 100644 --- a/src/client/debug_menu.h +++ b/src/client/debug_menu.h @@ -5,6 +5,7 @@ typedef enum { ENTRY_VERSION, ENTRY_FPS, ENTRY_POS, + ENTRY_POINTED, ENTRY_YAW, ENTRY_PITCH, ENTRY_TIME, diff --git a/src/client/game.c b/src/client/game.c index c0554eb..8891b18 100644 --- a/src/client/game.c +++ b/src/client/game.c @@ -1,13 +1,13 @@ -#define STB_IMAGE_WRITE_IMPLEMENTATION #include #include #include -#include #include #include #include "client/camera.h" #include "client/client.h" #include "client/client_entity.h" +#include "client/client_inventory.h" +#include "client/client_item.h" #include "client/client_node.h" #include "client/client_player.h" #include "client/client_terrain.h" @@ -26,25 +26,7 @@ int game_fps = 0; -static void crosshair_init() -{ - gui_add(NULL, (GUIElementDefinition) { - .pos = {0.5f, 0.5f}, - .z_index = 0.0f, - .offset = {0, 0}, - .margin = {0, 0}, - .align = {0.5f, 0.5f}, - .scale = {1.0f, 1.0f}, - .scale_type = SCALE_IMAGE, - .affect_parent_scale = false, - .text = NULL, - .image = texture_load(RESSOURCE_PATH "textures/crosshair.png", false), - .text_color = {0.0f, 0.0f, 0.0f, 0.0f}, - .bg_color = {0.0f, 0.0f, 0.0f, 0.0f}, - }); -} - -static void render(f64 dtime) +void game_render(f64 dtime) { glEnable(GL_DEPTH_TEST); GL_DEBUG glEnable(GL_BLEND); GL_DEBUG @@ -60,6 +42,7 @@ static void render(f64 dtime) frustum_update(); terrain_gfx_update(); client_entity_gfx_update(); + client_inventory_update(); sky_render(); model_scene_render(dtime); @@ -98,7 +81,7 @@ static void game_loop() debug_menu_changed(ENTRY_SUN_ANGLE); debug_menu_update(); - render(dtime); + game_render(dtime); glfwSwapBuffers(window.handle); glfwPollEvents(); @@ -126,23 +109,27 @@ bool game(Flag *gfx_init) client_player_gfx_init(); - if (!interact_init()) + camera_init(); + + if (!gui_init()) return false; - client_node_init(); - client_terrain_start(); + if (!interact_init()) + return false; - camera_set_position((v3f32) {0.0f, 0.0f, 0.0f}); - camera_set_angle(0.0f, 0.0f); + client_item_init(); - if (!gui_init()) + if (!client_inventory_init()) return false; + client_node_init(); + client_terrain_start(); + debug_menu_init(); - crosshair_init(); input_init(); flag_set(gfx_init); + game_loop(); client_terrain_stop(); @@ -155,70 +142,9 @@ bool game(Flag *gfx_init) client_entity_gfx_deinit(); client_player_gfx_deinit(); interact_deinit(); + client_item_deinit(); + client_inventory_deinit(); return true; } -char *game_take_screenshot() -{ - // renderbuffer for depth & stencil buffer - GLuint rbo; - glGenRenderbuffers(1, &rbo); GL_DEBUG - glBindRenderbuffer(GL_RENDERBUFFER, rbo); GL_DEBUG - glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH24_STENCIL8, window.width, window.height); GL_DEBUG - - // 2 textures, one with AA, one without - - GLuint txos[2]; - glGenTextures(2, txos); GL_DEBUG - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, txos[0]); GL_DEBUG - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGB, window.width, window.height, GL_TRUE); GL_DEBUG - - glBindTexture(GL_TEXTURE_2D, txos[1]); GL_DEBUG - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window.width, window.height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); GL_DEBUG - - // 2 framebuffers, one with AA, one without - - GLuint fbos[2]; - glGenFramebuffers(2, fbos); GL_DEBUG - - glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, txos[0], 0); GL_DEBUG - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); GL_DEBUG - - glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, txos[1], 0); GL_DEBUG - - // render scene - glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG - render(0.0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); GL_DEBUG - - // blit AA-buffer into no-AA buffer - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); GL_DEBUG - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); GL_DEBUG - glBlitFramebuffer(0, 0, window.width, window.height, 0, 0, window.width, window.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_DEBUG - - // read data - GLubyte data[window.width * window.height * 3]; - glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG - glPixelStorei(GL_PACK_ALIGNMENT, 1); GL_DEBUG - glReadPixels(0, 0, window.width, window.height, GL_RGB, GL_UNSIGNED_BYTE, data); GL_DEBUG - - // create filename - char filename[BUFSIZ]; - time_t timep = time(0); - strftime(filename, BUFSIZ, "screenshot-%Y-%m-%d-%H:%M:%S.png", localtime(&timep)); - - // save screenshot - stbi_flip_vertically_on_write(true); - stbi_write_png(filename, window.width, window.height, 3, data, window.width * 3); - - // delete buffers - glDeleteRenderbuffers(1, &rbo); GL_DEBUG - glDeleteTextures(2, txos); GL_DEBUG - glDeleteFramebuffers(2, fbos); GL_DEBUG - - return strdup(filename); -} diff --git a/src/client/game.h b/src/client/game.h index af1d74c..107583a 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -2,10 +2,11 @@ #define _GAME_H_ #include +#include "types.h" extern int game_fps; bool game(Flag *gfx_init); -char *game_take_screenshot(); +void game_render(f64 dtime); #endif // _GAME_H_ diff --git a/src/client/gui.c b/src/client/gui.c index 4aecb48..05f4fb7 100644 --- a/src/client/gui.c +++ b/src/client/gui.c @@ -327,7 +327,7 @@ void gui_render() glEnable(GL_CULL_FACE); GL_DEBUG } -GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def) +GUIElement *gui_add(GUIElement *parent, GUIElementDef def) { if (parent == NULL) parent = &root_element; diff --git a/src/client/gui.h b/src/client/gui.h index ea4b15e..1ce9584 100644 --- a/src/client/gui.h +++ b/src/client/gui.h @@ -29,10 +29,10 @@ typedef struct { Texture *image; v4f32 text_color; v4f32 bg_color; -} GUIElementDefinition; +} GUIElementDef; typedef struct GUIElement { - GUIElementDefinition def; + GUIElementDef def; bool visible; v2f32 pos; v2f32 scale; @@ -47,7 +47,7 @@ bool gui_init(); void gui_deinit(); void gui_update_projection(); void gui_render(); -GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def); +GUIElement *gui_add(GUIElement *parent, GUIElementDef def); void gui_text(GUIElement *element, const char *text); void gui_transform(GUIElement *element); diff --git a/src/client/input.c b/src/client/input.c index 19dc81c..00ede8a 100644 --- a/src/client/input.c +++ b/src/client/input.c @@ -6,9 +6,9 @@ #include "client/client.h" #include "client/client_player.h" #include "client/debug_menu.h" -#include "client/game.h" #include "client/gui.h" #include "client/input.h" +#include "client/screenshot.h" #include "client/window.h" #include "day.h" @@ -72,7 +72,7 @@ static bool key_listener(KeyListener *listener) void input_init() { - pause_menu = gui_add(NULL, (GUIElementDefinition) { + pause_menu = gui_add(NULL, (GUIElementDef) { .pos = {0.0f, 0.0f}, .z_index = 0.5f, .offset = {0, 0}, @@ -87,7 +87,7 @@ void input_init() .bg_color = {0.0f, 0.0f, 0.0f, 0.4f}, }); - status_message = gui_add(NULL, (GUIElementDefinition) { + status_message = gui_add(NULL, (GUIElementDef) { .pos = {0.5f, 0.25f}, .z_index = 0.1f, .offset = {0, 0}, @@ -165,7 +165,7 @@ void input_tick(f64 dtime) debug_menu_toggle(); if (key_listener(&listener_screenshot)) { - char *screenshot_filename = game_take_screenshot(); + char *screenshot_filename = screenshot(); SET_STATUS_MESSAGE("Screenshot saved to %s", screenshot_filename) free(screenshot_filename); } @@ -202,7 +202,7 @@ void input_cursor(double current_x, double current_y) cursor_last_x = current_x; cursor_last_y = current_y; - ClientEntity *entity = client_player_entity(); + ClientEntity *entity = client_player_entity_local(); if (!entity) return; diff --git a/src/client/interact.c b/src/client/interact.c index 728bc29..a4c2251 100644 --- a/src/client/interact.c +++ b/src/client/interact.c @@ -3,15 +3,17 @@ #include "client/camera.h" #include "client/client_node.h" #include "client/cube.h" +#include "client/debug_menu.h" #include "client/frustum.h" #include "client/gl_debug.h" +#include "client/gui.h" #include "client/interact.h" #include "client/mesh.h" #include "client/raycast.h" #include "client/shader.h" -static bool pointed; -static v3s32 node_pos; +struct InteractPointed interact_pointed; + static GLuint shader_prog; static GLint loc_MVP; static GLint loc_color; @@ -53,6 +55,21 @@ bool interact_init() selection_mesh.data = vertices; mesh_upload(&selection_mesh); + gui_add(NULL, (GUIElementDef) { + .pos = {0.5f, 0.5f}, + .z_index = 0.0f, + .offset = {0, 0}, + .margin = {0, 0}, + .align = {0.5f, 0.5f}, + .scale = {1.0f, 1.0f}, + .scale_type = SCALE_IMAGE, + .affect_parent_scale = false, + .text = NULL, + .image = texture_load(RESSOURCE_PATH "textures/crosshair.png", false), + .text_color = {0.0f, 0.0f, 0.0f, 0.0f}, + .bg_color = {0.0f, 0.0f, 0.0f, 0.0f}, + }); + return true; } @@ -64,22 +81,27 @@ void interact_deinit() void interact_tick() { - v3s32 old_node_pos = node_pos; - - NodeType node; - if ((pointed = raycast( - (v3f64) {camera.eye [0], camera.eye [1], camera.eye [2]}, - (v3f64) {camera.front[0], camera.front[1], camera.front[2]}, - 5, &node_pos, &node)) && !v3s32_equals(node_pos, old_node_pos)) { - mat4x4_translate(model, node_pos.x, node_pos.y, node_pos.z); - v3f32 *color = &client_node_definitions[node].selection_color; + bool old_exists = interact_pointed.exists; + v3s32 old_pointed = interact_pointed.pos; + if ((interact_pointed.exists = raycast( + (v3f64) {camera.eye [0], camera.eye [1], camera.eye [2]}, + (v3f64) {camera.front[0], camera.front[1], camera.front[2]}, + 5, &interact_pointed.pos, &interact_pointed.node)) + && !v3s32_equals(interact_pointed.pos, old_pointed)) { + mat4x4_translate(model, + interact_pointed.pos.x, interact_pointed.pos.y, interact_pointed.pos.z); + v3f32 *color = &client_node_defs[interact_pointed.node].selection_color; glProgramUniform3f(shader_prog, loc_color, color->x, color->y, color->z); GL_DEBUG + debug_menu_changed(ENTRY_POINTED); } + + if (old_exists && !interact_pointed.exists) + debug_menu_changed(ENTRY_POINTED); } void interact_render() { - if (!pointed) + if (!interact_pointed.exists) return; mat4x4 mvp; diff --git a/src/client/interact.h b/src/client/interact.h index 707bb01..aa3389d 100644 --- a/src/client/interact.h +++ b/src/client/interact.h @@ -1,6 +1,12 @@ #ifndef _INTERACT_H_ #define _INTERACT_H_ +extern struct InteractPointed { + bool exists; + v3s32 pos; + NodeType node; +} interact_pointed; + bool interact_init(); void interact_deinit(); void interact_tick(); diff --git a/src/client/mesh.c b/src/client/mesh.c index 49df506..d778ce1 100644 --- a/src/client/mesh.c +++ b/src/client/mesh.c @@ -1,8 +1,133 @@ +#include #include +#include #include +#include "client/cube.h" #include "client/gl_debug.h" #include "client/mesh.h" +typedef struct { + v3s32 pos; + v3f32 color; +} LoadedVoxel; + +typedef struct { + Tree voxels; + Array vertices; +} LoadedRenderArgs; + +static v3s32 face_dir[6] = { + {+0, +0, -1}, + {+0, +0, +1}, + {-1, +0, +0}, + {+1, +0, +0}, + {+0, -1, +0}, + {+0, +1, +0}, +}; + +typedef struct { + v3f32 pos; + v3f32 normal; + v3f32 color; +} __attribute__((packed)) LoadedVertex; +static VertexLayout loaded_layout = { + .attributes = (VertexAttribute[]) { + {GL_FLOAT, 3, sizeof(v3f32)}, // position + {GL_FLOAT, 3, sizeof(v3f32)}, // normal + {GL_FLOAT, 3, sizeof(v3f32)}, // color + }, + .count = 3, + .size = sizeof(LoadedVertex), +}; + +static int cmp_loaded_voxel(const LoadedVoxel *voxel, const v3s32 *pos) +{ + return v3s32_cmp(&voxel->pos, pos); +} + +static void render_loaded_voxel(LoadedVoxel *voxel, LoadedRenderArgs *args) +{ + v3f32 pos = v3s32_to_f32(voxel->pos); + for (int f = 0; f < 6; f++) { + v3s32 neigh_pos = v3s32_add(voxel->pos, face_dir[f]); + if (tree_get(&args->voxels, &neigh_pos, &cmp_loaded_voxel, NULL)) + continue; + + for (int v = 0; v < 6; v++) + array_apd(&args->vertices, &(LoadedVertex) { + v3f32_add(cube_vertices[f][v].position, pos), + cube_vertices[f][v].normal, + voxel->color, + }); + } +} + +void mesh_load(Mesh *mesh, const char *path) +{ + mesh->layout = &loaded_layout; + mesh->vao = mesh->vbo = 0; + mesh->data = NULL; + mesh->count = 0; + mesh->free_data = true; + + LoadedRenderArgs args; + tree_ini(&args.voxels); + array_ini(&args.vertices, sizeof(LoadedVertex), 500); + + FILE *file = fopen(path, "r"); + if (!file) { + fprintf(stderr, "[warning] failed to open mesh %s\n", path); + return; + } + + char *line = NULL; + size_t siz = 0; + ssize_t length; + int count = 0; + + while ((length = getline(&line, &siz, file)) > 0) { + count++; + + if (*line == '#') + continue; + + LoadedVoxel *voxel = malloc(sizeof *voxel); + + v3s32 color; + if (sscanf(line, "%d %d %d %2x%2x%2x", + &voxel->pos.x, &voxel->pos.z, &voxel->pos.y, + &color.x, &color.y, &color.z) != 6) { + fprintf(stderr, "[warning] syntax error in mesh %s in line %d: %s\n", + path, count, line); + free(voxel); + continue; + } + + voxel->color = (v3f32) { + (f32) color.x / 0xFF, + (f32) color.y / 0xFF, + (f32) color.z / 0xFF, + }; + + if (!tree_add(&args.voxels, &voxel->pos, voxel, &cmp_loaded_voxel, NULL)) { + fprintf(stderr, "[warning] more than one voxel at position (%d, %d, %d) in mesh %s in line %d\n", + voxel->pos.x, voxel->pos.y, voxel->pos.z, path, count); + free(voxel); + } + } + + if (line) + free(line); + + fclose(file); + + tree_trv(&args.voxels, &render_loaded_voxel, &args, NULL, 0); + tree_clr(&args.voxels, &free, NULL, NULL, 0); + + mesh->data = args.vertices.ptr; + mesh->count = args.vertices.siz; +} + // upload data to GPU (only done once) void mesh_upload(Mesh *mesh) { diff --git a/src/client/mesh.h b/src/client/mesh.h index 3597043..15c598b 100644 --- a/src/client/mesh.h +++ b/src/client/mesh.h @@ -25,6 +25,7 @@ typedef struct { bool free_data; } Mesh; +void mesh_load(Mesh *mesh, const char *path); void mesh_upload(Mesh *mesh); void mesh_render(Mesh *mesh); void mesh_destroy(Mesh *mesh); diff --git a/src/client/model.c b/src/client/model.c index 3a8ba6c..8954267 100644 --- a/src/client/model.c +++ b/src/client/model.c @@ -55,9 +55,16 @@ static void render_node(ModelNode *node) if (!node->visible) return; + if (node->clockwise) { + glFrontFace(GL_CW); GL_DEBUG + } + for (size_t i = 0; i < node->meshes.siz; i++) { ModelMesh *mesh = &((ModelMesh *) node->meshes.ptr)[i]; + if (!mesh->mesh) + continue; + glUseProgram(mesh->shader->prog); GL_DEBUG glUniformMatrix4fv(mesh->shader->loc_transform, 1, GL_FALSE, node->abs[0]); GL_DEBUG @@ -70,6 +77,10 @@ static void render_node(ModelNode *node) } list_itr(&node->children, &render_node, NULL, NULL); + + if (node->clockwise) { + glFrontFace(GL_CCW); GL_DEBUG + } } static void free_node_meshes(ModelNode *node) @@ -276,11 +287,15 @@ Model *model_load(const char *path, const char *textures_path, Mesh *cube, Model cursor += n; else fprintf(stderr, "[warning] invalid value for rot in model %s in line %d\n", path, count); + + node->rot = v3f32_scale(node->rot, M_PI / 180.0); } else if (strcmp(key, "scale") == 0) { if (sscanf(cursor, "%f %f %f %n", &node->scale.x, &node->scale.y, &node->scale.z, &n) == 3) cursor += n; else fprintf(stderr, "[warning] invalid value for scale in model %s in line %d\n", path, count); + } else if (strcmp(key, "clockwise") == 0) { + node->clockwise = 1; } else if (strcmp(key, "cube") == 0) { char texture[length + 1]; @@ -372,7 +387,8 @@ ModelNode *model_node_create(ModelNode *parent) { ModelNode *node = malloc(sizeof *node); node->name = NULL; - node->visible = true; + node->visible = 1; + node->clockwise = 0; node->pos = (v3f32) {0.0f, 0.0f, 0.0f}; node->rot = (v3f32) {0.0f, 0.0f, 0.0f}; node->scale = (v3f32) {1.0f, 1.0f, 1.0f}; diff --git a/src/client/model.h b/src/client/model.h index 977dbc6..8ca5ed2 100644 --- a/src/client/model.h +++ b/src/client/model.h @@ -26,12 +26,13 @@ typedef struct { typedef struct ModelNode { char *name; - bool visible; v3f32 pos, rot, scale; mat4x4 abs, rel; Array meshes; struct ModelNode *parent; List children; + unsigned int visible: 1; + unsigned int clockwise: 1; } ModelNode; typedef struct { diff --git a/src/client/raycast.c b/src/client/raycast.c index fba282d..c1f4a93 100644 --- a/src/client/raycast.c +++ b/src/client/raycast.c @@ -14,7 +14,7 @@ bool raycast(v3f64 pos, v3f64 dir, f64 len, v3s32 *node_pos, NodeType *node) if (*node == NODE_UNLOADED) return false; - if (client_node_definitions[*node].pointable) + if (client_node_defs[*node].pointable) return true; f64 vpos[3] = {pos.x, pos.y, pos.z}; diff --git a/src/client/screenshot.c b/src/client/screenshot.c new file mode 100644 index 0000000..0a388f2 --- /dev/null +++ b/src/client/screenshot.c @@ -0,0 +1,73 @@ +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include +#include +#include +#include +#include +#include "client/game.h" +#include "client/gl_debug.h" +#include "client/window.h" + +char *screenshot() +{ + // renderbuffer for depth & stencil buffer + GLuint rbo; + glGenRenderbuffers(1, &rbo); GL_DEBUG + glBindRenderbuffer(GL_RENDERBUFFER, rbo); GL_DEBUG + glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH24_STENCIL8, window.width, window.height); GL_DEBUG + + // 2 textures, one with AA, one without + + GLuint txos[2]; + glGenTextures(2, txos); GL_DEBUG + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, txos[0]); GL_DEBUG + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGB, window.width, window.height, GL_TRUE); GL_DEBUG + + glBindTexture(GL_TEXTURE_2D, txos[1]); GL_DEBUG + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window.width, window.height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); GL_DEBUG + + // 2 framebuffers, one with AA, one without + + GLuint fbos[2]; + glGenFramebuffers(2, fbos); GL_DEBUG + + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, txos[0], 0); GL_DEBUG + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); GL_DEBUG + + glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, txos[1], 0); GL_DEBUG + + // render scene + glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG + game_render(0.0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); GL_DEBUG + + // blit AA-buffer into no-AA buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); GL_DEBUG + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); GL_DEBUG + glBlitFramebuffer(0, 0, window.width, window.height, 0, 0, window.width, window.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_DEBUG + + // read data + GLubyte data[window.width * window.height * 3]; + glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG + glPixelStorei(GL_PACK_ALIGNMENT, 1); GL_DEBUG + glReadPixels(0, 0, window.width, window.height, GL_RGB, GL_UNSIGNED_BYTE, data); GL_DEBUG + + // create filename + char filename[BUFSIZ]; + time_t timep = time(0); + strftime(filename, BUFSIZ, "screenshot-%Y-%m-%d-%H:%M:%S.png", localtime(&timep)); + + // save screenshot + stbi_flip_vertically_on_write(true); + stbi_write_png(filename, window.width, window.height, 3, data, window.width * 3); + + // delete buffers + glDeleteRenderbuffers(1, &rbo); GL_DEBUG + glDeleteTextures(2, txos); GL_DEBUG + glDeleteFramebuffers(2, fbos); GL_DEBUG + + return strdup(filename); +} diff --git a/src/client/screenshot.h b/src/client/screenshot.h new file mode 100644 index 0000000..06de0df --- /dev/null +++ b/src/client/screenshot.h @@ -0,0 +1,6 @@ +#ifndef _SCREENSHOT_H_ +#define _SCREENSHOT_H_ + +char *screenshot(); + +#endif // _SCREENSHOT_H_ diff --git a/src/client/shader.c b/src/client/shader.c index fcf358a..1a54271 100644 --- a/src/client/shader.c +++ b/src/client/shader.c @@ -5,7 +5,7 @@ #include "client/gl_debug.h" #include "client/shader.h" -static GLuint compile_shader(GLenum type, const char *path, const char *name, GLuint program, const char *definitions) +static GLuint compile_shader(GLenum type, const char *path, const char *name, GLuint program, const char *defs) { char full_path[strlen(path) + 1 + strlen(name) + 1 + 4 + 1]; sprintf(full_path, "%s/%s.glsl", path, name); @@ -53,13 +53,13 @@ static GLuint compile_shader(GLenum type, const char *path, const char *name, GL const char *code_list[3] = { version, - definitions, + defs, code, }; int size_list[3] = { 18, - strlen(definitions), + strlen(defs), size, }; @@ -82,21 +82,21 @@ static GLuint compile_shader(GLenum type, const char *path, const char *name, GL return id; } -bool shader_program_create(const char *path, GLuint *idptr, const char *definitions) +bool shader_program_create(const char *path, GLuint *idptr, const char *defs) { GLuint id = glCreateProgram(); GL_DEBUG - if (!definitions) - definitions = ""; + if (!defs) + defs = ""; GLuint vert, frag; - if (!(vert = compile_shader(GL_VERTEX_SHADER, path, "vertex", id, definitions))) { + if (!(vert = compile_shader(GL_VERTEX_SHADER, path, "vertex", id, defs))) { glDeleteProgram(id); GL_DEBUG return false; } - if (!(frag = compile_shader(GL_FRAGMENT_SHADER, path, "fragment", id, definitions))) { + if (!(frag = compile_shader(GL_FRAGMENT_SHADER, path, "fragment", id, defs))) { glDeleteShader(vert); GL_DEBUG glDeleteProgram(id); GL_DEBUG return false; diff --git a/src/client/shader.h b/src/client/shader.h index eb62941..b53b604 100644 --- a/src/client/shader.h +++ b/src/client/shader.h @@ -5,6 +5,6 @@ #include #include -bool shader_program_create(const char *path, GLuint *idptr, const char *definitions); +bool shader_program_create(const char *path, GLuint *idptr, const char *defs); #endif // _SHADER_H_ diff --git a/src/client/terrain_gfx.c b/src/client/terrain_gfx.c index 258a295..52877d9 100644 --- a/src/client/terrain_gfx.c +++ b/src/client/terrain_gfx.c @@ -59,7 +59,7 @@ static ModelShader model_shader; static inline bool cull_face(NodeType self, NodeType nbr) { - switch (client_node_definitions[self].visibility) { + switch (client_node_defs[self].visibility) { case VISIBILITY_CLIP: return false; @@ -69,7 +69,7 @@ static inline bool cull_face(NodeType self, NodeType nbr) case VISIBILITY_SOLID: return nbr == NODE_UNLOADED - || client_node_definitions[nbr].visibility == VISIBILITY_SOLID; + || client_node_defs[nbr].visibility == VISIBILITY_SOLID; default: // impossible break; @@ -85,7 +85,7 @@ static inline void render_node(ChunkRenderData *data, v3s32 offset) args.node = &data->chunk->data[offset.x][offset.y][offset.z]; - ClientNodeDefinition *def = &client_node_definitions[args.node->type]; + ClientNodeDef *def = &client_node_defs[args.node->type]; if (def->visibility == VISIBILITY_NONE) return; diff --git a/src/client/window.h b/src/client/window.h index 0203510..7f657e3 100644 --- a/src/client/window.h +++ b/src/client/window.h @@ -2,6 +2,9 @@ #define _WINDOW_H_ #include +#include +#include +#include "types.h" extern struct Window { int width, height; diff --git a/src/item.c b/src/item.c new file mode 100644 index 0000000..25a1a2c --- /dev/null +++ b/src/item.c @@ -0,0 +1,98 @@ +#include +#include "item.h" + +void item_stack_initialize(ItemStack *stack) +{ + stack->type = ITEM_NONE; + stack->count = 1; + stack->data = NULL; + + if (item_defs[stack->type].create) + item_defs[stack->type].create(stack); +} + +void item_stack_destroy(ItemStack *stack) +{ + if (item_defs[stack->type].delete) + item_defs[stack->type].delete(stack); + + if (stack->data) { + free(stack->data); + stack->data = NULL; + } +} + +void item_stack_set(ItemStack *stack, ItemType type, u32 count, Blob buffer) +{ + item_stack_destroy(stack); + + stack->type = type; + stack->count = count; + stack->data = item_defs[stack->type].data_size > 0 ? + malloc(item_defs[stack->type].data_size) : NULL; + + if (item_defs[stack->type].create) + item_defs[stack->type].create(stack); + + if (item_defs[stack->type].deserialize) + item_defs[stack->type].deserialize(&buffer, stack->data); +} + +void item_stack_serialize(ItemStack *stack, SerializedItemStack *serialized) +{ + serialized->type = stack->type; + serialized->count = stack->count; + serialized->data = (Blob) {0, NULL}; + + if (item_defs[stack->type].serialize) + item_defs[stack->type].serialize(&serialized->data, stack->data); +} + +void item_stack_deserialize(ItemStack *stack, SerializedItemStack *serialized) +{ + ItemType type = serialized->type; + + if (type >= COUNT_ITEM) + type = ITEM_UNKNOWN; + + item_stack_set(stack, type, serialized->count, serialized->data); +} + +ItemDef item_defs[COUNT_ITEM] = { + // unknown + { + .stackable = false, + .data_size = 0, + .create = NULL, + .delete = NULL, + .serialize = NULL, + .deserialize = NULL, + }, + // none + { + .stackable = false, + .data_size = 0, + .create = NULL, + .delete = NULL, + .serialize = NULL, + .deserialize = NULL, + }, + // pickaxe + { + .stackable = false, + .data_size = 0, + .create = NULL, + .delete = NULL, + .serialize = NULL, + .deserialize = NULL, + }, + // axe + { + .stackable = false, + .data_size = 0, + .create = NULL, + .delete = NULL, + .serialize = NULL, + .deserialize = NULL, + }, +}; diff --git a/src/item.h b/src/item.h new file mode 100644 index 0000000..accf3ab --- /dev/null +++ b/src/item.h @@ -0,0 +1,40 @@ +#ifndef _ITEM_H_ +#define _ITEM_H_ + +#include +#include +#include "types.h" + +typedef enum { + ITEM_UNKNOWN, + ITEM_NONE, + ITEM_PICKAXE, + ITEM_AXE, + COUNT_ITEM, +} ItemType; + +typedef struct { + ItemType type; + u32 count; // i know future me is going to thank me for making it big + void *data; +} ItemStack; + +typedef struct { + bool stackable; + size_t data_size; + void (*create)(ItemStack *stack); + void (*delete)(ItemStack *stack); + void (*serialize)(Blob *buffer, void *data); + void (*deserialize)(Blob *buffer, void *data); +} ItemDef; + +void item_stack_initialize(ItemStack *stack); +void item_stack_destroy(ItemStack *stack); + +void item_stack_set(ItemStack *stack, ItemType type, u32 count, Blob buffer); +void item_stack_serialize(ItemStack *stack, SerializedItemStack *serialized); +void item_stack_deserialize(ItemStack *stack, SerializedItemStack *serialized); + +extern ItemDef item_defs[]; + +#endif // _ITEM_H_ diff --git a/src/node.c b/src/node.c index 727f81c..c9c2c1c 100644 --- a/src/node.c +++ b/src/node.c @@ -2,7 +2,7 @@ #include "terrain.h" #include "types.h" -NodeDefinition node_definitions[NODE_UNLOADED] = { +NodeDef node_defs[NODE_UNLOADED] = { // unknown { .solid = true, diff --git a/src/node.h b/src/node.h index 3e7e930..b660d17 100644 --- a/src/node.h +++ b/src/node.h @@ -5,8 +5,6 @@ #include #include "types.h" -#define NODE_DEFINITION(type) ((type) < NODE_UNLOADED ? &node_definitions[NODE_UNKNOWN] : &node_definitions[(type)]); - typedef enum { NODE_UNKNOWN, // Used for unknown nodes received from server (caused by outdated clients) NODE_AIR, @@ -36,8 +34,8 @@ typedef struct { void (*delete)(struct TerrainNode *node); void (*serialize)(Blob *buffer, void *data); void (*deserialize)(Blob *buffer, void *data); -} NodeDefinition; +} NodeDef; -extern NodeDefinition node_definitions[]; +extern NodeDef node_defs[]; #endif diff --git a/src/physics.c b/src/physics.c index 8f117b4..a89e89c 100644 --- a/src/physics.c +++ b/src/physics.c @@ -20,7 +20,7 @@ static aabb3s32 round_box(aabb3f64 box) static bool is_solid(Terrain *terrain, s32 x, s32 y, s32 z) { NodeType node = terrain_get_node(terrain, (v3s32) {x, y, z}).type; - return node == NODE_UNLOADED || node_definitions[node].solid; + return node == NODE_UNLOADED || node_defs[node].solid; } bool physics_ground(Terrain *terrain, bool collide, aabb3f32 box, v3f64 *pos, v3f64 *vel) diff --git a/src/server/server.c b/src/server/server.c index 0cbaed3..114f654 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -1,8 +1,9 @@ #define _GNU_SOURCE // don't worry, GNU extensions are only used when available #include +#include #include #include -#include +#include #include "interrupt.h" #include "server/database.h" #include "server/server.h" @@ -70,6 +71,8 @@ int main(int argc, char **argv) server->on_recv_type[DRAGONNET_TYPE_ToServerPosRot ] = (void *) &on_ToServerPosRot; server->on_recv_type[DRAGONNET_TYPE_ToServerRequestChunk] = (void *) &on_ToServerRequestChunk; + srand(time(0)); + interrupt_init(); if (!database_init()) return EXIT_FAILURE; diff --git a/src/server/server_player.c b/src/server/server_player.c index 61b666c..4a41d5e 100644 --- a/src/server/server_player.c +++ b/src/server/server_player.c @@ -27,32 +27,50 @@ static void send_entity_add(ServerPlayer *player, ServerPlayer *entity) }); } -static void send_entity_remove(ServerPlayer *player, ServerPlayer *entity) +static void send_entity_remove(ServerPlayer *client, ServerPlayer *entity) { - dragonnet_peer_send_ToClientEntityRemove(player->peer, &(ToClientEntityRemove) { + dragonnet_peer_send_ToClientEntityRemove(client->peer, &(ToClientEntityRemove) { .id = entity->id, }); } -static void send_entity_update_pos_rot(ServerPlayer *player, ServerPlayer *entity) +static void send_entity_update_pos_rot(ServerPlayer *client, ServerPlayer *entity) { - if (player != entity) - dragonnet_peer_send_ToClientEntityUpdatePosRot(player->peer, &(ToClientEntityUpdatePosRot) { + if (client != entity) + dragonnet_peer_send_ToClientEntityUpdatePosRot(client->peer, &(ToClientEntityUpdatePosRot) { .id = entity->id, .pos = entity->pos, .rot = entity->rot, }); } -static void send_entity_add_existing(ServerPlayer *entity, ServerPlayer *player) +static void send_entity_add_existing(ServerPlayer *entity, ServerPlayer *client) { - if (player != entity) { + if (client != entity) { pthread_rwlock_rdlock(&entity->lock_pos); - send_entity_add(player, entity); + send_entity_add(client, entity); pthread_rwlock_unlock(&entity->lock_pos); } } +static void send_player_inventory(ServerPlayer *client, ServerPlayer *player) +{ + ToClientPlayerInventory pkt; + pkt.id = player->id; + item_stack_serialize(&player->inventory.left, &pkt.left); + item_stack_serialize(&player->inventory.right, &pkt.right); + dragonnet_peer_send_ToClientPlayerInventory(client->peer, &pkt); +} + +static void send_player_inventory_existing(ServerPlayer *player, ServerPlayer *client) +{ + if (client != player) { + pthread_rwlock_rdlock(&player->lock_inv); + send_player_inventory(client, player); + pthread_rwlock_unlock(&player->lock_inv); + } +} + // main thread // called on server shutdown static void player_drop(ServerPlayer *player) @@ -81,6 +99,10 @@ static void player_delete(ServerPlayer *player) pthread_rwlock_destroy(&player->lock_pos); + item_stack_destroy(&player->inventory.left); + item_stack_destroy(&player->inventory.right); + pthread_rwlock_destroy(&player->lock_inv); + free(player); } @@ -95,6 +117,9 @@ static void player_spawn(ServerPlayer *player) database_create_player(player->name, player->pos, player->rot); } + item_stack_set(&player->inventory.left, ITEM_NONE + rand() % (ITEM_AXE - ITEM_NONE + 1), 1, (Blob) {0, NULL}); + item_stack_set(&player->inventory.right, ITEM_NONE + rand() % (ITEM_AXE - ITEM_NONE + 1), 1, (Blob) {0, NULL}); + // since this is recv thread, we don't need lock_peer dragonnet_peer_send_ToClientInfo(player->peer, &(ToClientInfo) { .seed = seed, @@ -113,6 +138,9 @@ static void player_spawn(ServerPlayer *player) server_player_iterate(&send_entity_add, player); server_player_iterate(&send_entity_add_existing, player); + + server_player_iterate(&send_player_inventory, player); + server_player_iterate(&send_player_inventory_existing, player); } // any thread @@ -170,6 +198,10 @@ void server_player_add(DragonnetPeer *peer) player->rot = (v3f32) {0.0f, 0.0f, 0.0f}; pthread_rwlock_init(&player->lock_pos, NULL); + item_stack_initialize(&player->inventory.left); + item_stack_initialize(&player->inventory.right); + pthread_rwlock_init(&player->lock_inv, NULL); + printf("[access] connected %s\n", player->name); peer->extra = refcount_grb(&player->rc); diff --git a/src/server/server_player.h b/src/server/server_player.h index 1d20a5d..34af225 100644 --- a/src/server/server_player.h +++ b/src/server/server_player.h @@ -5,6 +5,7 @@ #include #include #include +#include "item.h" #include "types.h" typedef struct { @@ -21,6 +22,12 @@ typedef struct { v3f64 pos; // player position v3f32 rot; // you wont guess what this is pthread_rwlock_t lock_pos; // git commit crime + + struct { + ItemStack left; + ItemStack right; + } inventory; + pthread_rwlock_t lock_inv; } ServerPlayer; void server_player_init(); diff --git a/src/server/server_terrain.c b/src/server/server_terrain.c index f6a22da..77b9475 100644 --- a/src/server/server_terrain.c +++ b/src/server/server_terrain.c @@ -263,7 +263,7 @@ static void generate_spawn_hut() pos.y++; } - if (node_definitions[node].solid) + if (node_defs[node].solid) break; server_terrain_gen_node(pos, diff --git a/src/server/terrain_gen.c b/src/server/terrain_gen.c index b258b1d..6d5a239 100644 --- a/src/server/terrain_gen.c +++ b/src/server/terrain_gen.c @@ -95,7 +95,7 @@ void terrain_gen_chunk(TerrainChunk *chunk, List *changed_chunks) node = NODE_SNOW; if (generate_args.diff == 1) for (int i = 0; i < NUM_TREES; i++) { - TreeDef *def = &tree_definitions[i]; + TreeDef *def = &tree_defs[i]; if (def->condition(&condition_args) && noise2d(condition_args.pos.x, condition_args.pos.z, 0, seed + def->offset) * 0.5 + 0.5 < def->probability diff --git a/src/server/trees.c b/src/server/trees.c index 2d165c2..e013a0d 100644 --- a/src/server/trees.c +++ b/src/server/trees.c @@ -201,7 +201,7 @@ static void palm_tree(v3s32 pos, List *changed_chunks) voxel_procedural_delete(proc); } -TreeDef tree_definitions[NUM_TREES] = { +TreeDef tree_defs[NUM_TREES] = { // oak { .spread = 64.0f, diff --git a/src/server/trees.h b/src/server/trees.h index 8084c52..2eeb3f8 100644 --- a/src/server/trees.h +++ b/src/server/trees.h @@ -30,6 +30,6 @@ typedef struct { void (*generate)(v3s32 pos, List *changed_chunks); } TreeDef; -extern TreeDef tree_definitions[]; +extern TreeDef tree_defs[]; #endif // _TREES_H_ diff --git a/src/terrain.c b/src/terrain.c index 2e8eec8..b3366c8 100644 --- a/src/terrain.c +++ b/src/terrain.c @@ -166,7 +166,7 @@ Blob terrain_serialize_chunk(TerrainChunk *chunk) }, }; - NodeDefinition *def = &node_definitions[node->type]; + NodeDef *def = &node_defs[node->type]; if (def->serialize) def->serialize(&node_data->data, node->data); @@ -242,7 +242,7 @@ TerrainNode terrain_node_create(NodeType type, Blob buffer) if (type >= NODE_UNLOADED) type = NODE_UNKNOWN; - NodeDefinition *def = &node_definitions[type]; + NodeDef *def = &node_defs[type]; TerrainNode node; node.type = type; @@ -259,7 +259,7 @@ TerrainNode terrain_node_create(NodeType type, Blob buffer) void terrain_node_delete(TerrainNode node) { - NodeDefinition *def = &node_definitions[node.type]; + NodeDef *def = &node_defs[node.type]; if (def->delete) def->delete(&node); diff --git a/src/types.def b/src/types.def index 48c572b..8248726 100644 --- a/src/types.def +++ b/src/types.def @@ -25,6 +25,11 @@ EntityData v3f32 rot String nametag +SerializedItemStack + u32 type + u32 count + Blob data + ; server packets pkt ToServerAuth @@ -83,3 +88,8 @@ pkt ToClientEntityUpdatePosRot pkt ToClientEntityUpdateNametag u64 id String nametag + +pkt ToClientPlayerInventory + u64 id + SerializedItemStack left + SerializedItemStack right -- 2.44.0