world: rebake chunk tex on change

isolation_bkp/dynres
Dominik Madarász 2021-07-27 13:30:43 +02:00
parent d0ff81b570
commit 0cb52303ae
10 changed files with 105 additions and 20 deletions

View File

@ -38,6 +38,8 @@ typedef struct entity_view {
// TODO(zaklaus): Find a way to stream dynamic arrays
uint8_t blocks_used;
uint8_t blocks[256];
uint32_t color;
uint8_t is_dirty;
int64_t tex;
// NOTE(zaklaus): internals

View File

@ -36,6 +36,7 @@ typedef struct {
uint8_t active_layer_id;
ecs_world_t *ecs;
ecs_query_t *ecs_update;
ecs_entity_t chunk_handle;
ecs_entity_t *chunk_mapping;
librg_world *tracker;
world_pkt_reader_proc *reader_proc;
@ -62,8 +63,17 @@ ecs_entity_t world_chunk_mapping(librg_chunk id);
typedef struct {
uint32_t id;
uint8_t block_id;
ecs_entity_t chunk_id;
ecs_entity_t chunk_e;
int64_t chunk_id;
float ox, oy;
} world_block_lookup;
world_block_lookup world_block_from_realpos(float x, float y);
world_block_lookup world_block_from_realpos(float x, float y);
world_block_lookup world_block_from_index(int64_t id, uint16_t block_idx);
int64_t world_chunk_from_realpos(float x, float y);
int64_t world_chunk_from_entity(ecs_entity_t id);
void world_chunk_replace_block(int64_t id, uint16_t block_idx, uint8_t block_id);
uint8_t *world_chunk_get_blocks(int64_t id);
void world_chunk_mark_dirty(ecs_entity_t e);
uint8_t world_chunk_is_dirty(ecs_entity_t e);

View File

@ -33,7 +33,7 @@ static WORLD_PKT_READER(pkt_reader) {
pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, data, datalen);
header.udata = udata;
if (ok && header.ok) {
return pkt_handlers[header.id].handler(&header) >= 0;
} else {
@ -111,7 +111,7 @@ void game_init(game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t
world_viewers_init(num_viewers);
active_viewer = &world_viewers[0];
camera_reset();
if (game_mode == GAMEKIND_CLIENT) {
world_setup_pkt_handlers(pkt_reader, mp_pkt_writer);
network_init();
@ -135,7 +135,7 @@ int8_t game_is_networked() {
void game_shutdown() {
world_viewers_destroy();
if (game_mode == GAMEKIND_CLIENT) {
network_client_disconnect();
network_destroy();
@ -152,12 +152,12 @@ void game_input() {
platform_input();
}
void game_update() {
void game_update() {
if (game_mode == GAMEKIND_CLIENT) {
network_client_tick();
}
else world_update();
game_world_cleanup_entities();
}
@ -179,14 +179,14 @@ void game_world_cleanup_entities(void) {
static uint64_t last_removal_time = 0;
if (last_removal_time > zpl_time_rel_ms()) return;
last_removal_time = zpl_time_rel_ms() + GAME_ENT_REMOVAL_TIME;
for (int i = 0; i < zpl_buffer_count(world_viewers); i += 1){
entity_view_tbl *view = &world_viewers[i].entities;
uint32_t deletions = 0;
for (int j = 0; j < zpl_array_count(view->entries); j += 1) {
if (deletions > GAME_ENT_REMOVAL_TRESHOLD) return;
entity_view *e = &view->entries[j].value;
if (e->tran_effect == ETRAN_REMOVE) {
entity_view_tbl_remove(view, e->ent_id);

View File

@ -172,7 +172,7 @@ void DEBUG_draw_ground(uint64_t key, entity_view * data) {
DrawTextureRec(tex.texture, (Rectangle){0, 0, tex.texture.width, -tex.texture.height}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
if (zoom_overlay_tran > 0.02f) {
DrawRectangleEco(x, y, size-offset, size-offset, ColorAlpha(ColorFromHSV(key*x, 0.13f, 0.89f), data->tran_time*zoom_overlay_tran*0.75f));
DrawRectangleEco(x, y, size-offset, size-offset, ColorAlpha(ColorFromHSV(data->color, 0.13f, 0.89f), data->tran_time*zoom_overlay_tran*0.75f));
DrawTextEco(TextFormat("%d %d", (int)data->x, (int)data->y), (int16_t)x+15, (int16_t)y+15, 200 , ColorAlpha(BLACK, data->tran_time*zoom_overlay_tran), 0.0);

View File

@ -112,6 +112,8 @@ void *blocks_get_chunk_tex(uint64_t id) {
}
void blocks_remove_chunk_tex(uint64_t id) {
UnloadRenderTexture(*blocks__chunk_tbl_get(&baked_chunks, id));
RenderTexture2D *tex = blocks__chunk_tbl_get(&baked_chunks, id);
if (!tex) return;
UnloadRenderTexture(*tex);
blocks__chunk_tbl_remove(&baked_chunks, id);
}

View File

@ -19,6 +19,7 @@ entity_view world_build_entity_view(int64_t e) {
ECS_IMPORT(world_ecs(), Net);
entity_view view = {0};
// TODO(zaklaus): branch out based on ECS tags
const Position *pos = ecs_get(world_ecs(), e, Position);
if (pos) {
@ -34,12 +35,15 @@ entity_view world_build_entity_view(int64_t e) {
view.vy = vel->y;
}
const Chunk *chpos = ecs_get(world_ecs(), e, Chunk);
if (chpos) {
if (ecs_get(world_ecs(), e, Chunk)) {
Chunk *chpos = ecs_get_mut(world_ecs(), e, Chunk, 0);
view.kind = EKIND_CHUNK;
view.x = chpos->x;
view.y = chpos->y;
view.blocks_used = 1;
view.is_dirty = chpos->is_dirty;
chpos->is_dirty = false;
for (int i = 0; i < world.chunk_size*world.chunk_size; i += 1) {
view.blocks[i] = world.block_mapping[chpos->id][i];
@ -84,7 +88,7 @@ int32_t tracker_write_update(librg_world *w, librg_event *e) {
// NOTE(zaklaus): exclude chunks from updates as they never move
// TODO(zaklaus): use dirty flag to send updates if chunk changes
{
if (view.kind == EKIND_CHUNK) {
if (view.kind == EKIND_CHUNK && !view.is_dirty) {
return LIBRG_WRITE_REJECT;
}
}
@ -141,6 +145,7 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) {
world.ecs_update = ecs_query_new(world.ecs, "net.ClientInfo, general.Position");
world.chunk_mapping = zpl_malloc(sizeof(ecs_entity_t)*zpl_square(chunk_amount));
world.block_mapping = zpl_malloc(sizeof(uint8_t*)*zpl_square(chunk_amount));
world.chunk_handle = ecs_typeid(Chunk);
int32_t world_build_status = worldgen_test(&world);
ZPL_ASSERT(world_build_status >= 0);
@ -154,6 +159,7 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) {
world.chunk_mapping[i] = e;
world.block_mapping[i] = zpl_malloc(sizeof(uint8_t)*zpl_square(chunk_size));
chunk->id = i;
chunk->is_dirty = false;
for (int y = 0; y < chunk_size; y += 1) {
for (int x = 0; x < chunk_size; x += 1) {
@ -226,6 +232,8 @@ static void world_tracker_update(uint8_t ticker, uint32_t freq, uint8_t radius)
int32_t world_update() {
ECS_IMPORT(world.ecs, General);
profile (PROF_UPDATE_SYSTEMS) {
ecs_progress(world.ecs, 0.0f);
}
@ -308,10 +316,53 @@ world_block_lookup world_block_from_realpos(float x, float y) {
world_block_lookup lookup = {
.id = block_idx,
.block_id = block_id,
.chunk_id = e,
.chunk_id = chunk_id,
.chunk_e = e,
.ox = box,
.oy = boy,
};
return lookup;
}
world_block_lookup world_block_from_index(int64_t id, uint16_t block_idx) {
uint8_t block_id = world.block_mapping[id][block_idx];
world_block_lookup lookup = {
.id = block_idx,
.block_id = block_id,
.chunk_id = id,
.chunk_e = world.chunk_mapping[id],
};
return lookup;
}
int64_t world_chunk_from_realpos(float x, float y) {
librg_chunk chunk_id = librg_chunk_from_realpos(world.tracker, x, y, 0);
return world.chunk_mapping[chunk_id];
}
int64_t world_chunk_from_entity(ecs_entity_t id) {
return librg_entity_chunk_get(world.tracker, id);
}
void world_chunk_replace_block(int64_t id, uint16_t block_idx, uint8_t block_id) {
assert(block_idx >= 0 && block_idx < zpl_square(world.chunk_size));
world.block_mapping[id][block_idx] = block_id;
}
uint8_t *world_chunk_get_blocks(int64_t id) {
return world.block_mapping[id];
}
void world_chunk_mark_dirty(ecs_entity_t e) {
Chunk *chunk = (Chunk *)ecs_get_mut_w_entity(world.ecs, e, world.chunk_handle, NULL);
if (chunk) chunk->is_dirty = true;
}
uint8_t world_chunk_is_dirty(ecs_entity_t e) {
Chunk *chunk = (Chunk *)ecs_get_mut_w_entity(world.ecs, e, world.chunk_handle, NULL);
if (chunk) return chunk->is_dirty;
return false;
}

View File

@ -40,6 +40,8 @@ int32_t tracker_read_update(librg_world *w, librg_event *e) {
data.layer_id = view->active_layer_id;
predict_receive_update(d, &data);
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);
return 0;
}
@ -53,6 +55,7 @@ int32_t tracker_read_create(librg_world *w, librg_event *e) {
data.ent_id = entity_id;
data.layer_id = view->active_layer_id;
data.tran_time = 0.0f;
data.color = rand(); // TODO(zaklaus): feed from server
if (data.flag & EFLAG_INTERP) {
data.tx = data.x;
data.ty = data.y;

View File

@ -12,7 +12,7 @@ ECS_STRUCT(Chunk, {
uint32_t id;
int16_t x;
int16_t y;
//ecs_vector(uint8_t) blocks;
uint8_t is_dirty;
});
ECS_STRUCT(Drawable, {

View File

@ -4,6 +4,8 @@
#include "modules/general.h"
#include "modules/physics.h"
#include "world/blocks.h"
#define PLR_MOVE_SPEED 50.0
#define PLR_MOVE_SPEED_MULT 4.0
@ -32,6 +34,20 @@ void DemoNPCMoveAround(ecs_iter_t *it) {
}
}
void DemoPlaceIceBlock(ecs_iter_t *it) {
Input *in = ecs_column(it, Input, 1);
Position *p = ecs_column(it, Position, 2);
uint8_t watr_id = blocks_find(BLOCK_BIOME_DEV, BLOCK_KIND_WATER);
for (int i = 0; i < it->count; i++) {
if (in[i].use) {
world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y);
world_chunk_replace_block(l.chunk_id, l.id, watr_id);
world_chunk_mark_dirty(l.chunk_e);
}
}
}
void ControllersImport(ecs_world_t *ecs) {
ECS_MODULE(ecs, Controllers);
ecs_set_name_prefix(ecs, "Controllers");
@ -48,6 +64,7 @@ void ControllersImport(ecs_world_t *ecs) {
ECS_TAG(ecs, EcsDemoNPC);
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, Input, physics.Velocity);
ECS_SYSTEM(ecs, DemoPlaceIceBlock, EcsOnLoad, Input, general.Position);
ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, physics.Velocity, EcsDemoNPC);
ECS_PREFAB(ecs, Base, general.Position, physics.Velocity, Input, EcsActor);

View File

@ -3,14 +3,14 @@
void GeneralImport(ecs_world_t *ecs) {
ECS_MODULE(ecs, General);
ecs_set_name_prefix(ecs, "General");
ECS_IMPORT(ecs, FlecsMeta);
ECS_META(ecs, Position);
ECS_META(ecs, Chunk);
ECS_META(ecs, Vector2D);
ECS_META(ecs, Drawable);
ECS_SET_COMPONENT(Chunk);
ECS_SET_COMPONENT(Vector2D);
ECS_SET_COMPONENT(Position);