diff --git a/code/foundation/src/gui/build_mode.c b/code/foundation/src/gui/build_mode.c index 4b53320..3fafcc0 100644 --- a/code/foundation/src/gui/build_mode.c +++ b/code/foundation/src/gui/build_mode.c @@ -69,7 +69,7 @@ void buildmode_draw(void) { qty = item->quantity; } - world_block_lookup l = world_block_from_realpos((float)cam.x, (float)cam.y); + world_view_block_lookup l = world_view_block_from_realpos(game_world_view_get_active(), (float)cam.x, (float)cam.y); if (build_is_deletion_mode && !l.is_outer){ renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(RED, 0.4f)); goto build_skip_placements; diff --git a/code/foundation/src/world/entity_view.c b/code/foundation/src/world/entity_view.c index ed38e8b..2df938f 100644 --- a/code/foundation/src/world/entity_view.c +++ b/code/foundation/src/world/entity_view.c @@ -15,7 +15,8 @@ pkt_desc pkt_entity_view_desc[] = { { PKT_HALF(entity_view, vx) }, { PKT_HALF(entity_view, vy) }, - { PKT_SKIP_IF(entity_view, blocks_used, 0, 2) }, // NOTE(zaklaus): skip blocks for anything else + { PKT_SKIP_IF(entity_view, blocks_used, 0, 3) }, // NOTE(zaklaus): skip blocks for anything else + { PKT_UINT(entity_view, chk_id) }, { PKT_ARRAY(entity_view, blocks) }, { PKT_ARRAY(entity_view, outer_blocks) }, diff --git a/code/foundation/src/world/entity_view.h b/code/foundation/src/world/entity_view.h index 97c6936..72aa643 100644 --- a/code/foundation/src/world/entity_view.h +++ b/code/foundation/src/world/entity_view.h @@ -47,6 +47,7 @@ typedef struct entity_view { float max_hp; // TODO(zaklaus): Find a way to stream dynamic arrays + uint32_t chk_id; uint8_t blocks_used; block_id blocks[256]; block_id outer_blocks[256]; diff --git a/code/foundation/src/world/world.c b/code/foundation/src/world/world.c index d5cfaf1..6b847c6 100644 --- a/code/foundation/src/world/world.c +++ b/code/foundation/src/world/world.c @@ -108,6 +108,7 @@ entity_view *world_build_entity_view(int64_t e) { Chunk *chunk = 0; if ((chunk = ecs_get_mut_if(world_ecs(), e, Chunk))) { + view.chk_id = chunk->id; view.x = chunk->x; view.y = chunk->y; view.blocks_used = 1; diff --git a/code/foundation/src/world/world_view.c b/code/foundation/src/world/world_view.c index cab8b35..7f6365d 100644 --- a/code/foundation/src/world/world_view.c +++ b/code/foundation/src/world/world_view.c @@ -11,6 +11,12 @@ int32_t tracker_read_remove(librg_world *w, librg_event *e) { int64_t entity_id = librg_event_entity_get(w, e); world_view *view = (world_view*)librg_world_userdata_get(w); + entity_view *ent = entity_view_get(&view->entities, entity_id); + + if (ent && ent->kind == EKIND_CHUNK) { + world_view_clear_chunk(view, ent); + } + entity_view_remove_chunk_texture(&view->entities, entity_id); entity_view_destroy(&view->entities, entity_id); return 0; @@ -40,6 +46,11 @@ int32_t tracker_read_update(librg_world *w, librg_event *e) { entity_view_update_or_create(&view->entities, entity_id, data); entity_view_remove_chunk_texture(&view->entities, entity_id); entity_view_update_chunk_texture(&view->entities, entity_id, view); + + if (data.kind == EKIND_CHUNK) { + entity_view *chk = entity_view_get(&view->entities, entity_id); + world_view_setup_chunk(view, chk); + } return 0; } @@ -62,6 +73,11 @@ int32_t tracker_read_create(librg_world *w, librg_event *e) { entity_view_update_or_create(&view->entities, entity_id, data); entity_view_mark_for_fadein(&view->entities, entity_id); entity_view_update_chunk_texture(&view->entities, entity_id, view); + + if (data.kind == EKIND_CHUNK) { + entity_view *chk = entity_view_get(&view->entities, entity_id); + world_view_setup_chunk(view, chk); + } return 0; } @@ -79,10 +95,14 @@ void world_view_init(world_view *view, uint32_t seed, uint64_t ent_id, uint16_t view->chunk_size = chunk_size; view->chunk_amount = chunk_amount; view->dim = WORLD_BLOCK_SIZE * chunk_size * chunk_amount; + view->chk_dim = chunk_size * chunk_amount; view->size = view->dim * view->dim; + view->chunk_mapping = zpl_malloc(sizeof(entity_view*)*zpl_square(view->chunk_amount)); + view->block_mapping = zpl_malloc(sizeof(block_id*)*zpl_square(view->chunk_amount)); + view->outer_block_mapping = zpl_malloc(sizeof(block_id*)*zpl_square(view->chunk_amount)); librg_config_chunksize_set(view->tracker, WORLD_BLOCK_SIZE * chunk_size, WORLD_BLOCK_SIZE * chunk_size, 1); - librg_config_chunkamount_set(view->tracker, chunk_amount, chunk_amount, 1); + librg_config_chunkamount_set(view->tracker, chunk_amount, chunk_amount, 0); librg_config_chunkoffset_set(view->tracker, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG); librg_event_set(view->tracker, LIBRG_READ_CREATE, tracker_read_create); @@ -92,6 +112,83 @@ void world_view_init(world_view *view, uint32_t seed, uint64_t ent_id, uint16_t } void world_view_destroy(world_view *view) { + zpl_mfree(view->chunk_mapping); + for (int i = 0; i < zpl_square(view->chunk_amount); i+=1) { + zpl_mfree(view->block_mapping[i]); + zpl_mfree(view->outer_block_mapping[i]); + } + zpl_mfree(view->block_mapping); + zpl_mfree(view->outer_block_mapping); librg_world_destroy(view->tracker); entity_view_free(&view->entities); } + +void world_view_setup_chunk(world_view *view, entity_view *chk) { + librg_chunk chunk_id = chk->chk_id; + view->chunk_mapping[chunk_id] = chk; + if (!view->block_mapping[chunk_id]) + view->block_mapping[chunk_id] = zpl_malloc(sizeof(block_id)*zpl_square(view->chunk_size)); + if (!view->outer_block_mapping[chunk_id]) + view->outer_block_mapping[chunk_id] = zpl_malloc(sizeof(block_id)*zpl_square(view->chunk_size)); + + for (int i = 0; i < zpl_square(view->chunk_size); i += 1) { + view->block_mapping[chunk_id][i] = chk->blocks[i]; + view->outer_block_mapping[chunk_id][i] = chk->outer_blocks[i]; + } +} + +void world_view_clear_chunk(world_view *view, entity_view *chk) { + librg_chunk chunk_id = chk->chk_id; + view->chunk_mapping[chunk_id] = NULL; + zpl_mfree(view->block_mapping[chunk_id]); view->block_mapping[chunk_id] = NULL; + zpl_mfree(view->outer_block_mapping[chunk_id]); view->outer_block_mapping[chunk_id] = NULL; +} + +world_view_block_lookup world_view_block_from_realpos(world_view *view, float x, float y) { + x = zpl_clamp(x, 0, view->dim-1); + y = zpl_clamp(y, 0, view->dim-1); + librg_chunk chunk_id = librg_chunk_from_realpos(view->tracker, x, y, 0); + entity_view *e = view->chunk_mapping[chunk_id]; + if (!e) { + return (world_view_block_lookup){0}; + } + int32_t size = view->chunk_size * WORLD_BLOCK_SIZE; + int16_t chunk_x, chunk_y; + librg_chunk_to_chunkpos(view->tracker, chunk_id, &chunk_x, &chunk_y, NULL); + + // NOTE(zaklaus): pos relative to chunk + float chx = x - chunk_x * size; + float chy = y - chunk_y * size; + + uint16_t bx = (uint16_t)chx / WORLD_BLOCK_SIZE; + uint16_t by = (uint16_t)chy / WORLD_BLOCK_SIZE; + uint16_t block_idx = (by*view->chunk_size)+bx; + block_id bid = view->outer_block_mapping[chunk_id][block_idx]; + bool is_outer = true; + if (bid == 0) { + bid = view->block_mapping[chunk_id][block_idx]; + is_outer = false; + } + + // NOTE(zaklaus): pos relative to block's center + float box = chx - bx * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f; + float boy = chy - by * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f; + + // NOTE(zaklaus): absolute pos in world. + float abox = (uint16_t)(x / WORLD_BLOCK_SIZE) * (float)WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2.0f; + float aboy = (uint16_t)(y / WORLD_BLOCK_SIZE) * (float)WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2.0f; + + world_view_block_lookup lookup = { + .id = block_idx, + .bid = bid, + .chunk_id = chunk_id, + .chunk_e = e, + .ox = box, + .oy = boy, + .aox = abox, + .aoy = aboy, + .is_outer = is_outer, + }; + + return lookup; +} diff --git a/code/foundation/src/world/world_view.h b/code/foundation/src/world/world_view.h index 838aa69..2b7c206 100644 --- a/code/foundation/src/world/world_view.h +++ b/code/foundation/src/world/world_view.h @@ -8,13 +8,17 @@ typedef struct { uint64_t owner_id; entity_view_tbl entities; librg_world *tracker; - + uint32_t seed; uint32_t size; - uint32_t dim; + uint32_t dim, chk_dim; uint16_t chunk_size; uint16_t chunk_amount; - + + block_id **block_mapping; + block_id **outer_block_mapping; + entity_view **chunk_mapping; + // NOTE(zaklaus): metrics float last_update[WORLD_TRACKER_LAYERS]; float delta_time[WORLD_TRACKER_LAYERS]; @@ -24,3 +28,18 @@ typedef struct { world_view world_view_create(uint16_t view_id); void world_view_init(world_view *view, uint32_t seed, uint64_t ent_id, uint16_t chunk_size, uint16_t chunk_amount); void world_view_destroy(world_view *view); + +void world_view_setup_chunk(world_view *view, entity_view *chk); +void world_view_clear_chunk(world_view *view, entity_view *chk); + +typedef struct { + uint16_t id; + block_id bid; + entity_view* chunk_e; + int64_t chunk_id; + float ox, oy; + float aox, aoy; + bool is_outer; +} world_view_block_lookup; + +world_view_block_lookup world_view_block_from_realpos(world_view *view, float x, float y);