world: rebake chunk tex on change
parent
d0ff81b570
commit
0cb52303ae
|
@ -38,6 +38,8 @@ typedef struct entity_view {
|
||||||
// TODO(zaklaus): Find a way to stream dynamic arrays
|
// TODO(zaklaus): Find a way to stream dynamic arrays
|
||||||
uint8_t blocks_used;
|
uint8_t blocks_used;
|
||||||
uint8_t blocks[256];
|
uint8_t blocks[256];
|
||||||
|
uint32_t color;
|
||||||
|
uint8_t is_dirty;
|
||||||
int64_t tex;
|
int64_t tex;
|
||||||
|
|
||||||
// NOTE(zaklaus): internals
|
// NOTE(zaklaus): internals
|
||||||
|
|
|
@ -36,6 +36,7 @@ typedef struct {
|
||||||
uint8_t active_layer_id;
|
uint8_t active_layer_id;
|
||||||
ecs_world_t *ecs;
|
ecs_world_t *ecs;
|
||||||
ecs_query_t *ecs_update;
|
ecs_query_t *ecs_update;
|
||||||
|
ecs_entity_t chunk_handle;
|
||||||
ecs_entity_t *chunk_mapping;
|
ecs_entity_t *chunk_mapping;
|
||||||
librg_world *tracker;
|
librg_world *tracker;
|
||||||
world_pkt_reader_proc *reader_proc;
|
world_pkt_reader_proc *reader_proc;
|
||||||
|
@ -62,8 +63,17 @@ ecs_entity_t world_chunk_mapping(librg_chunk id);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint8_t block_id;
|
uint8_t block_id;
|
||||||
ecs_entity_t chunk_id;
|
ecs_entity_t chunk_e;
|
||||||
|
int64_t chunk_id;
|
||||||
float ox, oy;
|
float ox, oy;
|
||||||
} world_block_lookup;
|
} 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);
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ static WORLD_PKT_READER(pkt_reader) {
|
||||||
pkt_header header = {0};
|
pkt_header header = {0};
|
||||||
uint32_t ok = pkt_header_decode(&header, data, datalen);
|
uint32_t ok = pkt_header_decode(&header, data, datalen);
|
||||||
header.udata = udata;
|
header.udata = udata;
|
||||||
|
|
||||||
if (ok && header.ok) {
|
if (ok && header.ok) {
|
||||||
return pkt_handlers[header.id].handler(&header) >= 0;
|
return pkt_handlers[header.id].handler(&header) >= 0;
|
||||||
} else {
|
} 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);
|
world_viewers_init(num_viewers);
|
||||||
active_viewer = &world_viewers[0];
|
active_viewer = &world_viewers[0];
|
||||||
camera_reset();
|
camera_reset();
|
||||||
|
|
||||||
if (game_mode == GAMEKIND_CLIENT) {
|
if (game_mode == GAMEKIND_CLIENT) {
|
||||||
world_setup_pkt_handlers(pkt_reader, mp_pkt_writer);
|
world_setup_pkt_handlers(pkt_reader, mp_pkt_writer);
|
||||||
network_init();
|
network_init();
|
||||||
|
@ -135,7 +135,7 @@ int8_t game_is_networked() {
|
||||||
|
|
||||||
void game_shutdown() {
|
void game_shutdown() {
|
||||||
world_viewers_destroy();
|
world_viewers_destroy();
|
||||||
|
|
||||||
if (game_mode == GAMEKIND_CLIENT) {
|
if (game_mode == GAMEKIND_CLIENT) {
|
||||||
network_client_disconnect();
|
network_client_disconnect();
|
||||||
network_destroy();
|
network_destroy();
|
||||||
|
@ -152,12 +152,12 @@ void game_input() {
|
||||||
platform_input();
|
platform_input();
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_update() {
|
void game_update() {
|
||||||
if (game_mode == GAMEKIND_CLIENT) {
|
if (game_mode == GAMEKIND_CLIENT) {
|
||||||
network_client_tick();
|
network_client_tick();
|
||||||
}
|
}
|
||||||
else world_update();
|
else world_update();
|
||||||
|
|
||||||
game_world_cleanup_entities();
|
game_world_cleanup_entities();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,14 +179,14 @@ void game_world_cleanup_entities(void) {
|
||||||
static uint64_t last_removal_time = 0;
|
static uint64_t last_removal_time = 0;
|
||||||
if (last_removal_time > zpl_time_rel_ms()) return;
|
if (last_removal_time > zpl_time_rel_ms()) return;
|
||||||
last_removal_time = zpl_time_rel_ms() + GAME_ENT_REMOVAL_TIME;
|
last_removal_time = zpl_time_rel_ms() + GAME_ENT_REMOVAL_TIME;
|
||||||
|
|
||||||
for (int i = 0; i < zpl_buffer_count(world_viewers); i += 1){
|
for (int i = 0; i < zpl_buffer_count(world_viewers); i += 1){
|
||||||
entity_view_tbl *view = &world_viewers[i].entities;
|
entity_view_tbl *view = &world_viewers[i].entities;
|
||||||
uint32_t deletions = 0;
|
uint32_t deletions = 0;
|
||||||
|
|
||||||
for (int j = 0; j < zpl_array_count(view->entries); j += 1) {
|
for (int j = 0; j < zpl_array_count(view->entries); j += 1) {
|
||||||
if (deletions > GAME_ENT_REMOVAL_TRESHOLD) return;
|
if (deletions > GAME_ENT_REMOVAL_TRESHOLD) return;
|
||||||
|
|
||||||
entity_view *e = &view->entries[j].value;
|
entity_view *e = &view->entries[j].value;
|
||||||
if (e->tran_effect == ETRAN_REMOVE) {
|
if (e->tran_effect == ETRAN_REMOVE) {
|
||||||
entity_view_tbl_remove(view, e->ent_id);
|
entity_view_tbl_remove(view, e->ent_id);
|
||||||
|
|
|
@ -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));
|
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) {
|
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);
|
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);
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,8 @@ void *blocks_get_chunk_tex(uint64_t id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void blocks_remove_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);
|
blocks__chunk_tbl_remove(&baked_chunks, id);
|
||||||
}
|
}
|
|
@ -19,6 +19,7 @@ entity_view world_build_entity_view(int64_t e) {
|
||||||
ECS_IMPORT(world_ecs(), Net);
|
ECS_IMPORT(world_ecs(), Net);
|
||||||
entity_view view = {0};
|
entity_view view = {0};
|
||||||
|
|
||||||
|
|
||||||
// TODO(zaklaus): branch out based on ECS tags
|
// TODO(zaklaus): branch out based on ECS tags
|
||||||
const Position *pos = ecs_get(world_ecs(), e, Position);
|
const Position *pos = ecs_get(world_ecs(), e, Position);
|
||||||
if (pos) {
|
if (pos) {
|
||||||
|
@ -34,12 +35,15 @@ entity_view world_build_entity_view(int64_t e) {
|
||||||
view.vy = vel->y;
|
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.kind = EKIND_CHUNK;
|
||||||
view.x = chpos->x;
|
view.x = chpos->x;
|
||||||
view.y = chpos->y;
|
view.y = chpos->y;
|
||||||
view.blocks_used = 1;
|
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) {
|
for (int i = 0; i < world.chunk_size*world.chunk_size; i += 1) {
|
||||||
view.blocks[i] = world.block_mapping[chpos->id][i];
|
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
|
// NOTE(zaklaus): exclude chunks from updates as they never move
|
||||||
// TODO(zaklaus): use dirty flag to send updates if chunk changes
|
// 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;
|
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.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.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.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);
|
int32_t world_build_status = worldgen_test(&world);
|
||||||
ZPL_ASSERT(world_build_status >= 0);
|
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.chunk_mapping[i] = e;
|
||||||
world.block_mapping[i] = zpl_malloc(sizeof(uint8_t)*zpl_square(chunk_size));
|
world.block_mapping[i] = zpl_malloc(sizeof(uint8_t)*zpl_square(chunk_size));
|
||||||
chunk->id = i;
|
chunk->id = i;
|
||||||
|
chunk->is_dirty = false;
|
||||||
|
|
||||||
for (int y = 0; y < chunk_size; y += 1) {
|
for (int y = 0; y < chunk_size; y += 1) {
|
||||||
for (int x = 0; x < chunk_size; x += 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() {
|
int32_t world_update() {
|
||||||
|
ECS_IMPORT(world.ecs, General);
|
||||||
|
|
||||||
profile (PROF_UPDATE_SYSTEMS) {
|
profile (PROF_UPDATE_SYSTEMS) {
|
||||||
ecs_progress(world.ecs, 0.0f);
|
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 = {
|
world_block_lookup lookup = {
|
||||||
.id = block_idx,
|
.id = block_idx,
|
||||||
.block_id = block_id,
|
.block_id = block_id,
|
||||||
.chunk_id = e,
|
.chunk_id = chunk_id,
|
||||||
|
.chunk_e = e,
|
||||||
.ox = box,
|
.ox = box,
|
||||||
.oy = boy,
|
.oy = boy,
|
||||||
};
|
};
|
||||||
|
|
||||||
return lookup;
|
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;
|
||||||
|
}
|
|
@ -40,6 +40,8 @@ int32_t tracker_read_update(librg_world *w, librg_event *e) {
|
||||||
data.layer_id = view->active_layer_id;
|
data.layer_id = view->active_layer_id;
|
||||||
predict_receive_update(d, &data);
|
predict_receive_update(d, &data);
|
||||||
entity_view_update_or_create(&view->entities, entity_id, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +55,7 @@ int32_t tracker_read_create(librg_world *w, librg_event *e) {
|
||||||
data.ent_id = entity_id;
|
data.ent_id = entity_id;
|
||||||
data.layer_id = view->active_layer_id;
|
data.layer_id = view->active_layer_id;
|
||||||
data.tran_time = 0.0f;
|
data.tran_time = 0.0f;
|
||||||
|
data.color = rand(); // TODO(zaklaus): feed from server
|
||||||
if (data.flag & EFLAG_INTERP) {
|
if (data.flag & EFLAG_INTERP) {
|
||||||
data.tx = data.x;
|
data.tx = data.x;
|
||||||
data.ty = data.y;
|
data.ty = data.y;
|
||||||
|
|
|
@ -12,7 +12,7 @@ ECS_STRUCT(Chunk, {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
int16_t x;
|
int16_t x;
|
||||||
int16_t y;
|
int16_t y;
|
||||||
//ecs_vector(uint8_t) blocks;
|
uint8_t is_dirty;
|
||||||
});
|
});
|
||||||
|
|
||||||
ECS_STRUCT(Drawable, {
|
ECS_STRUCT(Drawable, {
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "modules/general.h"
|
#include "modules/general.h"
|
||||||
#include "modules/physics.h"
|
#include "modules/physics.h"
|
||||||
|
|
||||||
|
#include "world/blocks.h"
|
||||||
|
|
||||||
#define PLR_MOVE_SPEED 50.0
|
#define PLR_MOVE_SPEED 50.0
|
||||||
#define PLR_MOVE_SPEED_MULT 4.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) {
|
void ControllersImport(ecs_world_t *ecs) {
|
||||||
ECS_MODULE(ecs, Controllers);
|
ECS_MODULE(ecs, Controllers);
|
||||||
ecs_set_name_prefix(ecs, "Controllers");
|
ecs_set_name_prefix(ecs, "Controllers");
|
||||||
|
@ -48,6 +64,7 @@ void ControllersImport(ecs_world_t *ecs) {
|
||||||
ECS_TAG(ecs, EcsDemoNPC);
|
ECS_TAG(ecs, EcsDemoNPC);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, Input, physics.Velocity);
|
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_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, physics.Velocity, EcsDemoNPC);
|
||||||
|
|
||||||
ECS_PREFAB(ecs, Base, general.Position, physics.Velocity, Input, EcsActor);
|
ECS_PREFAB(ecs, Base, general.Position, physics.Velocity, Input, EcsActor);
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
void GeneralImport(ecs_world_t *ecs) {
|
void GeneralImport(ecs_world_t *ecs) {
|
||||||
ECS_MODULE(ecs, General);
|
ECS_MODULE(ecs, General);
|
||||||
ecs_set_name_prefix(ecs, "General");
|
ecs_set_name_prefix(ecs, "General");
|
||||||
|
|
||||||
ECS_IMPORT(ecs, FlecsMeta);
|
ECS_IMPORT(ecs, FlecsMeta);
|
||||||
|
|
||||||
ECS_META(ecs, Position);
|
ECS_META(ecs, Position);
|
||||||
ECS_META(ecs, Chunk);
|
ECS_META(ecs, Chunk);
|
||||||
ECS_META(ecs, Vector2D);
|
ECS_META(ecs, Vector2D);
|
||||||
ECS_META(ecs, Drawable);
|
ECS_META(ecs, Drawable);
|
||||||
|
|
||||||
ECS_SET_COMPONENT(Chunk);
|
ECS_SET_COMPONENT(Chunk);
|
||||||
ECS_SET_COMPONENT(Vector2D);
|
ECS_SET_COMPONENT(Vector2D);
|
||||||
ECS_SET_COMPONENT(Position);
|
ECS_SET_COMPONENT(Position);
|
||||||
|
|
Loading…
Reference in New Issue