lots of changes

isolation
Dominik Madarász 2022-09-28 13:17:33 +00:00 committed by GitHub
parent b8e3decc96
commit 0be5d87ede
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 7969 additions and 3459 deletions

View File

@ -4,7 +4,7 @@ game_rulesdef game_rules = (game_rulesdef){
.phy_walk_drag = 4.23f, .phy_walk_drag = 4.23f,
.demo_npc_move_speed = 500, .demo_npc_move_speed = 500,
.demo_npc_steer_speed = 300, .demo_npc_steer_speed = 300,
.furnace_cook_time = 5.0f, .furnace_cook_time = 1.f,
.item_pick_radius = 25.0f, .item_pick_radius = 25.0f,
.item_merger_radius = 75.0f, .item_merger_radius = 75.0f,
.item_attract_radius = 75.0f, .item_attract_radius = 75.0f,

View File

@ -49,7 +49,7 @@ ActSpawnChest(void) {
void void
ActSpawnBelt(void) { ActSpawnBelt(void) {
ecs_entity_t e = item_spawn(ASSET_BELT, 999); ecs_entity_t e = item_spawn(ASSET_BELT, 32);
ecs_entity_t plr = camera_get().ent_id; ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position); Position const* origin = ecs_get(world_ecs(), plr, Position);

View File

@ -12,9 +12,12 @@ ECS_COMPONENT_DECLARE(Classify);
ECS_COMPONENT_DECLARE(Vehicle); ECS_COMPONENT_DECLARE(Vehicle);
ECS_COMPONENT_DECLARE(IsInVehicle); ECS_COMPONENT_DECLARE(IsInVehicle);
ECS_COMPONENT_DECLARE(Item); ECS_COMPONENT_DECLARE(Item);
ECS_COMPONENT_DECLARE(ItemAlreadyEdited);
ECS_COMPONENT_DECLARE(Inventory); ECS_COMPONENT_DECLARE(Inventory);
ECS_COMPONENT_DECLARE(ItemContainer); ECS_COMPONENT_DECLARE(ItemContainer);
ECS_COMPONENT_DECLARE(Furnace); ECS_COMPONENT_DECLARE(Furnace);
ECS_COMPONENT_DECLARE(Fuel);
ECS_COMPONENT_DECLARE(Ingredient);
ECS_COMPONENT_DECLARE(Device); ECS_COMPONENT_DECLARE(Device);
ECS_COMPONENT_DECLARE(DemoNPC); ECS_COMPONENT_DECLARE(DemoNPC);
ECS_COMPONENT_DECLARE(StreamInfo); ECS_COMPONENT_DECLARE(StreamInfo);
@ -34,9 +37,12 @@ void ComponentsImport(ecs_world_t *ecs) {
ECS_COMPONENT_DEFINE(ecs, Vehicle); ECS_COMPONENT_DEFINE(ecs, Vehicle);
ECS_COMPONENT_DEFINE(ecs, IsInVehicle); ECS_COMPONENT_DEFINE(ecs, IsInVehicle);
ECS_COMPONENT_DEFINE(ecs, Item); ECS_COMPONENT_DEFINE(ecs, Item);
ECS_COMPONENT_DEFINE(ecs, ItemAlreadyEdited);
ECS_COMPONENT_DEFINE(ecs, Inventory); ECS_COMPONENT_DEFINE(ecs, Inventory);
ECS_COMPONENT_DEFINE(ecs, ItemContainer); ECS_COMPONENT_DEFINE(ecs, ItemContainer);
ECS_COMPONENT_DEFINE(ecs, Furnace); ECS_COMPONENT_DEFINE(ecs, Furnace);
ECS_COMPONENT_DEFINE(ecs, Fuel);
ECS_COMPONENT_DEFINE(ecs, Ingredient);
ECS_COMPONENT_DEFINE(ecs, Device); ECS_COMPONENT_DEFINE(ecs, Device);
ECS_COMPONENT_DEFINE(ecs, DemoNPC); ECS_COMPONENT_DEFINE(ecs, DemoNPC);
ECS_COMPONENT_DEFINE(ecs, StreamInfo); ECS_COMPONENT_DEFINE(ecs, StreamInfo);

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "flecs/flecs.h" #include "flecs/flecs.h"
#include "gen/assets.h"
#ifndef ecs_get_mut_if #ifndef ecs_get_mut_if
#define ecs_get_mut_if(world, entity, component)\ #define ecs_get_mut_if(world, entity, component)\
@ -100,12 +101,17 @@ typedef struct {
uint16_t kind; uint16_t kind;
uint32_t quantity; uint32_t quantity;
float merger_time; float merger_time;
float durability; // 1.0 - 0.0 (0.0 = broken), we can only ever merge items of the same durability
} Item; } Item;
typedef struct {
char _unused;
} ItemAlreadyEdited;
typedef struct { typedef struct {
// TODO: we now hold a ref to an item, instead of representing an item slot, // TODO: we now hold a ref to an item, instead of representing an item slot,
// so that we can let the item entity keep its own components and also handle merging ops on its own. // so that we can let the item entity keep its own components and also handle merging ops on its own.
ecs_entity_t items[ITEMS_CONTAINER_SIZE]; ecs_entity_t items[ITEMS_INVENTORY_SIZE];
float pickup_time; float pickup_time;
} Inventory; } Inventory;
@ -114,18 +120,21 @@ typedef struct {
} ItemContainer; } ItemContainer;
typedef struct { typedef struct {
ecs_entity_t processed_item; asset_id processed_item;
float cook_time; float cook_time;
float burn_time; float burn_time;
} Furnace; } Furnace;
// typedef struct { typedef struct {
// float burn_time; asset_id kind;
// } Fuel; float burn_time;
} Fuel;
// typedef struct { typedef struct {
// asset_id converted_kind; asset_id producer;
// } FuelTank; asset_id additional_ingredient; // optional - can specify additional item we need in the container to craft this item
asset_id product;
} Ingredient;
typedef struct { typedef struct {
uint16_t asset; uint16_t asset;
@ -150,9 +159,12 @@ extern ECS_COMPONENT_DECLARE(Classify);
extern ECS_COMPONENT_DECLARE(Vehicle); extern ECS_COMPONENT_DECLARE(Vehicle);
extern ECS_COMPONENT_DECLARE(IsInVehicle); extern ECS_COMPONENT_DECLARE(IsInVehicle);
extern ECS_COMPONENT_DECLARE(Item); extern ECS_COMPONENT_DECLARE(Item);
extern ECS_COMPONENT_DECLARE(ItemAlreadyEdited);
extern ECS_COMPONENT_DECLARE(Inventory); extern ECS_COMPONENT_DECLARE(Inventory);
extern ECS_COMPONENT_DECLARE(ItemContainer); extern ECS_COMPONENT_DECLARE(ItemContainer);
extern ECS_COMPONENT_DECLARE(Furnace); extern ECS_COMPONENT_DECLARE(Furnace);
extern ECS_COMPONENT_DECLARE(Fuel);
extern ECS_COMPONENT_DECLARE(Ingredient);
extern ECS_COMPONENT_DECLARE(Device); extern ECS_COMPONENT_DECLARE(Device);
extern ECS_COMPONENT_DECLARE(DemoNPC); extern ECS_COMPONENT_DECLARE(DemoNPC);
extern ECS_COMPONENT_DECLARE(StreamInfo); extern ECS_COMPONENT_DECLARE(StreamInfo);

View File

@ -2,33 +2,42 @@ void FurnaceCook(ecs_iter_t *it) {
ItemContainer *storage = ecs_field(it, ItemContainer, 1); ItemContainer *storage = ecs_field(it, ItemContainer, 1);
Furnace *furnace = ecs_field(it, Furnace, 2); Furnace *furnace = ecs_field(it, Furnace, 2);
Position *p = ecs_field(it, Position, 3); Position *p = ecs_field(it, Position, 3);
Device *d = ecs_field(it, Device, 4);
for (int i = 0; i < it->count; i++) { for (int i = 0; i < it->count; i++) {
for (int j = 0; j < ITEMS_CONTAINER_SIZE; j++) { for (int j = 0; j < ITEMS_CONTAINER_SIZE; j++) {
if (storage[i].items[j].kind == ASSET_COAL) { ecs_entity_t item_slot_ent = storage[i].items[j];
// furnace[i].fuel_level += itemdb_get(storage[i].items[j].uuid, ITEMDB_FUEL_LEVEL); Item *item = item_get_data(item_slot_ent);
// furnace[i].fuel_level = zpl_clamp(furnace[i].fuel_level + 0.8f, 0.0f, 1.0f);
storage[i].items[j].quantity--; const Fuel *fuel = 0;
if (storage[i].items[j].quantity == 0) { if ((fuel = ecs_get(it->world, item_slot_ent, Fuel))) {
storage[i].items[j] = (ItemSlot){0}; if (fuel->kind == d->asset) {
furnace[i].burn_time += fuel->kind;
item_despawn(item_slot_ent);
storage[i].items[j] = 0;
} }
continue; continue;
} }
// if (furnace[i].fuel_level <= 0.0f) continue; // if (furnace[i].burn_time <= 0.0f) continue; TODO
if (furnace[i].cook_time < game_time()) { if (furnace[i].cook_time < game_time()) {
if (furnace[i].processed_item.kind > 0) { if (furnace[i].processed_item > 0) {
uint64_t e = item_spawn(furnace[i].processed_item.kind, 1); uint64_t e = item_spawn(furnace[i].processed_item, 1);
entity_set_position(e, p[i].x, p[i].y); entity_set_position(e, p[i].x, p[i].y);
furnace[i].processed_item.kind = 0; furnace[i].processed_item = 0;
} else { } else {
if (storage[i].items[j].kind == ASSET_DEMO_ICEMAKER) { const Ingredient *ing = 0;
furnace[i].processed_item.kind = ASSET_BELT; if ((ing = ecs_get(it->world, item_slot_ent, Ingredient))) {
storage[i].items[j].quantity--; if (ing->producer == d->asset) {
if (storage[i].items[j].quantity == 0) { furnace[i].processed_item = ing->product;
storage[i].items[j] = (ItemSlot){0}; furnace[i].cook_time = game_time() + game_rules.furnace_cook_time;
zpl_printf("e_id %llu, qty: %d\n", item_slot_ent, item->quantity);
item->quantity--;
if (item->quantity <= 0) {
item_despawn(item_slot_ent);
storage[i].items[j] = 0;
}
} }
furnace[i].cook_time = game_time() + game_rules.furnace_cook_time;
} }
} }
} }

View File

@ -8,12 +8,14 @@ void PickItem(ecs_iter_t *it) {
if (inv[i].pickup_time > game_time()) continue; if (inv[i].pickup_time > game_time()) continue;
size_t ents_count; size_t ents_count;
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2); int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
bool picked = false;
for (size_t j = 0; j < ents_count; j++) { for (size_t j = 0; j < ents_count; j++) {
Item *drop = 0; Item *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], Item))) { uint64_t ent_id = ents[j];
Position *p2 = ecs_get_mut(it->world, ents[j], Position); if ((drop = ecs_get_mut_if(it->world, ent_id, Item))) {
Velocity *v2 = ecs_get_mut(it->world, ents[j], Velocity); Position *p2 = ecs_get_mut(it->world, ent_id, Position);
Velocity *v2 = ecs_get_mut(it->world, ent_id, Velocity);
float dx = p2->x - p[i].x; float dx = p2->x - p[i].x;
float dy = p2->y - p[i].y; float dy = p2->y - p[i].y;
@ -21,23 +23,25 @@ void PickItem(ecs_iter_t *it) {
if (range <= game_rules.item_pick_radius) { if (range <= game_rules.item_pick_radius) {
uint16_t drop_id = item_find(drop->kind); uint16_t drop_id = item_find(drop->kind);
for (size_t k = 0; k < ITEMS_INVENTORY_SIZE; k += 1) { for (size_t k = 0; k < ITEMS_INVENTORY_SIZE; k += 1) {
ItemSlot *item_slot = &inv[i].items[k]; ecs_entity_t item_slot_ent = inv[i].items[k];
Item *item = item_get_data(item_slot->ent); Item *item = item_get_data(item_slot_ent);
uint16_t item_id = item_find(item->kind); uint16_t item_id = item ? item_find(item->kind) : 0;
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id) if (!item || (item_id != ASSET_INVALID && (item->kind == drop->kind && item->durability == drop->durability) && item->quantity < item_max_quantity(drop_id))) {
&& (item_slot->ent == 0 || item_slot->ent == ents[j])) { if (item) {
uint32_t picked_count = zpl_max(0, drop->quantity); uint32_t picked_count = zpl_max(0, drop->quantity);
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity); picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
item_slot->ent = ents[j]; item->quantity += picked_count;
item->quantity += picked_count; drop->quantity -= picked_count;
drop->quantity -= picked_count; item->kind = drop->kind;
item->kind = drop->kind;
entity_wake(ents[j]);
if (drop->quantity == 0) if (drop->quantity == 0)
item_show(ents[j], false); item_despawn(ent_id);
} else if (!world_entity_valid(item_slot_ent)) {
item_slot->ent = ents[j]; entity_wake(ent_id);
item_show(ent_id, false);
inv[i].items[k] = ent_id;
}
picked = true;
break; break;
} }
} }
@ -46,6 +50,8 @@ void PickItem(ecs_iter_t *it) {
v2->y = (p[i].y - p2->y) * game_rules.item_attract_force; v2->y = (p[i].y - p2->y) * game_rules.item_attract_force;
} }
} }
if (picked) break;
} }
} }
} }
@ -58,7 +64,7 @@ void DropItem(ecs_iter_t *it) {
for (int i = 0; i < it->count; i++) { for (int i = 0; i < it->count; i++) {
if (!in[i].drop) continue; if (!in[i].drop) continue;
ItemSlot *items = inv[i].items; ecs_entity_t *items = inv[i].items;
if (in[i].storage_action){ if (in[i].storage_action){
if (world_entity_valid(in[i].storage_ent)){ if (world_entity_valid(in[i].storage_ent)){
@ -73,8 +79,9 @@ void DropItem(ecs_iter_t *it) {
} }
} }
ItemSlot *item_slot = &items[in[i].storage_action ? in[i].storage_selected_item : in[i].selected_item]; uint8_t slot_id = in[i].storage_action ? in[i].storage_selected_item : in[i].selected_item;
Item *item = item_get_data(item_slot->ent); ecs_entity_t item_slot_ent = items[slot_id];
Item *item = item_get_data(item_slot_ent);
if (!item || item->quantity <= 0) if (!item || item->quantity <= 0)
continue; continue;
@ -83,72 +90,67 @@ void DropItem(ecs_iter_t *it) {
if (in[i].sprint) { if (in[i].sprint) {
dropped_count /= 2; dropped_count /= 2;
} else if (in[i].ctrl) { } else if (in[i].ctrl) {
dropped_count = dropped_count > 0 ? 1 : 0; dropped_count = item->quantity-1;
} }
if (dropped_count == 0) if (dropped_count == 0)
continue; continue;
ecs_entity_t te = item_slot->ent; item_show(item_slot_ent, true);
item_show(item_slot->ent, true);
item->quantity -= dropped_count;
ItemDrop *d = ecs_get_mut(world_ecs(), te, ItemDrop); Position *ipos = ecs_get_mut(it->world, item_slot_ent, Position);
*d = (ItemDrop){ entity_set_position(item_slot_ent, p[i].x, p[i].y);
.kind = item->kind,
.quantity = dropped_count,
.merger_time = game_time() + game_rules.item_drop_merger_time,
};
Position *ipos = ecs_get_mut(it->world, te, Position); Velocity *v = ecs_get_mut(it->world, item_slot_ent, Velocity);
*ipos = p[i];
Velocity *v = ecs_get_mut(it->world, te, Velocity);
v->x = in[i].mx * 800.0f; v->x = in[i].mx * 800.0f;
v->y = in[i].my * 800.0f; v->y = in[i].my * 800.0f;
inv[i].pickup_time = game_time() + game_rules.item_drop_pickup_time; inv[i].pickup_time = game_time() + game_rules.item_drop_pickup_time;
in[i].drop = false; in[i].drop = false;
items[slot_id] = 0;
if (item->quantity == 0) { if (item->quantity - dropped_count > 0) {
item->kind = 0; item->quantity -= dropped_count;
ecs_entity_t te = item_spawn(item->kind, dropped_count);
item_show(te, false);
items[slot_id] = te;
} }
} }
} }
void MergeItems(ecs_iter_t *it) { // void MergeItems(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1); // Position *p = ecs_field(it, Position, 1);
ItemDrop *id = ecs_field(it, ItemDrop, 2); // ItemDrop *id = ecs_field(it, ItemDrop, 2);
for (int i = 0; i < it->count; i += 1) { // for (int i = 0; i < it->count; i += 1) {
ItemDrop *item = &id[i]; // ItemDrop *item = &id[i];
if (item->merger_time < game_time()) // if (item->merger_time < game_time())
continue; // continue;
size_t ents_count; // size_t ents_count;
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 1); // int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 1);
for (size_t j = 0; j < ents_count; j++) { // for (size_t j = 0; j < ents_count; j++) {
ItemDrop *drop = 0; // ItemDrop *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) { // if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
if (drop->kind != item->kind || (ecs_entity_t)ents[j] == it->entities[i] || drop->quantity == 0 || item->quantity == 0) // if (drop->kind != item->kind || (ecs_entity_t)ents[j] == it->entities[i] || drop->quantity == 0 || item->quantity == 0)
continue; // continue;
Position const* p2 = ecs_get(it->world, ents[j], Position); // Position const* p2 = ecs_get(it->world, ents[j], Position);
float dx = p2->x - (p[i].x); // float dx = p2->x - (p[i].x);
float dy = p2->y - (p[i].y); // float dy = p2->y - (p[i].y);
float range = zpl_sqrt(dx*dx + dy*dy); // float range = zpl_sqrt(dx*dx + dy*dy);
if (range <= game_rules.item_merger_radius) { // if (range <= game_rules.item_merger_radius) {
drop->quantity += item->quantity; // drop->quantity += item->quantity;
item_despawn(it->entities[i]); // item_despawn(it->entities[i]);
break; // break;
} // }
} // }
} // }
} // }
} // }
void SwapItems(ecs_iter_t *it) { void SwapItems(ecs_iter_t *it) {
Input *in = ecs_field(it, Input, 1); Input *in = ecs_field(it, Input, 1);
@ -157,7 +159,7 @@ void SwapItems(ecs_iter_t *it) {
for (int i = 0; i < it->count; i++) { for (int i = 0; i < it->count; i++) {
if (!in[i].swap) continue; if (!in[i].swap) continue;
ItemDrop *items = inv[i].items; ecs_entity_t *items = inv[i].items;
if (in[i].storage_action){ if (in[i].storage_action){
if (world_entity_valid(in[i].storage_ent)){ if (world_entity_valid(in[i].storage_ent)){
@ -172,40 +174,49 @@ void SwapItems(ecs_iter_t *it) {
} }
} }
ItemDrop *to = 0; ecs_entity_t *from_ent = 0;
ItemDrop *from = 0; ecs_entity_t *to_ent = 0;
Item *to = 0;
Item *from = 0;
if (in[i].swap_storage){ if (in[i].swap_storage){
in[i].swap_storage = false; in[i].swap_storage = false;
if (in[i].storage_action){ if (in[i].storage_action){
from = &inv[i].items[in[i].swap_from]; from_ent = &inv[i].items[in[i].swap_from];
to = &items[in[i].swap_to]; to_ent = &items[in[i].swap_to];
from = item_get_data(*from_ent);
to = item_get_data(*to_ent);
}else{ }else{
if (world_entity_valid(in[i].storage_ent)){ if (world_entity_valid(in[i].storage_ent)){
ItemContainer *ic = 0; ItemContainer *ic = 0;
if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){ if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){
from = &ic->items[in[i].swap_from]; from_ent = &ic->items[in[i].swap_from];
from = item_get_data(*from_ent);
}else{ }else{
continue; continue;
} }
}else{ }else{
continue; continue;
} }
to = &items[in[i].swap_to]; to_ent = &items[in[i].swap_to];
to = item_get_data(*to_ent);
} }
}else{ }else{
from = &items[in[i].swap_from]; from_ent = &items[in[i].swap_from];
to = &items[in[i].swap_to]; to_ent = &items[in[i].swap_to];
from = item_get_data(*from_ent);
to = item_get_data(*to_ent);
} }
ZPL_ASSERT(from && to); if (!from) continue;
uint16_t to_id = item_find(to->kind); uint16_t to_id = to ? item_find(to->kind) : ASSET_EMPTY;
asset_id to_kind = to ? to->kind : ASSET_EMPTY;
if (to == from) { if (to_ent == from_ent) {
// NOTE(zaklaus): do nothing // NOTE(zaklaus): do nothing
} else if (to->kind == from->kind && to->quantity > 0) { } else if (to_kind == from->kind && to->quantity > 0) {
uint32_t swapped_count = from->quantity; uint32_t swapped_count = from->quantity;
if (in[i].sprint) { if (in[i].sprint) {
swapped_count /= 2; swapped_count /= 2;
@ -216,24 +227,28 @@ void SwapItems(ecs_iter_t *it) {
to->quantity += swapped_count; to->quantity += swapped_count;
from->quantity -= swapped_count; from->quantity -= swapped_count;
if (swapped_count == 0) { if (from->quantity == 0) {
ItemDrop tmp = *to; item_despawn(*from_ent);
*to = *from; *from_ent = 0;
*from = tmp;
} }
} else if ((in[i].ctrl || in[i].sprint) && to->quantity == 0 && from->quantity > 0) { } else if ((in[i].ctrl || in[i].sprint) && to == 0 && from->quantity > 0) {
// NOTE(zaklaus): item split // NOTE(zaklaus): item split
uint32_t split_count = from->quantity / 2; uint32_t split_count = from->quantity / 2;
if (in[i].ctrl) { if (in[i].ctrl) {
split_count = 1; split_count = 1;
} }
to->quantity = split_count; if (from->quantity - split_count == 0) {
continue;
}
ecs_entity_t te = item_spawn(from->kind, split_count);
item_show(te, false);
*to_ent = te;
from->quantity -= split_count; from->quantity -= split_count;
to->kind = from->kind;
} else { } else {
ItemDrop tmp = *to; ecs_entity_t tmp = *to_ent;
*to = *from; *to_ent = *from_ent;
*from = tmp; *from_ent = tmp;
} }
in[i].swap = false; in[i].swap = false;
@ -252,12 +267,13 @@ void UseItem(ecs_iter_t *it) {
continue; continue;
} }
ItemDrop *item = &inv[i].items[in[i].selected_item]; ecs_entity_t item_ent = inv[i].items[in[i].selected_item];
Item *item = item_get_data(item_ent);
uint16_t item_id = 0; uint16_t item_id = 0;
item_usage usage = UKIND_DELETE; item_usage usage = UKIND_DELETE;
if (!in[i].deletion_mode){ if (!in[i].deletion_mode){
item_id = item_find(item->kind); item_id = item ? item_find(item->kind) : ASSET_EMPTY;
usage = item_get_usage(item_id); usage = item_get_usage(item_id);
if (!item || item->quantity <= 0) continue; if (!item || item->quantity <= 0) continue;
} }
@ -268,7 +284,7 @@ void UseItem(ecs_iter_t *it) {
} }
} }
else if (in[i].use && usage > UKIND_END_PLACE) else if (in[i].use && usage > UKIND_END_PLACE)
item_use(it->world, item, p[i], 0); item_use(it->world, item_ent, item, p[i], 0);
else if (in[i].num_placements > 0 && usage < UKIND_END_PLACE) { else if (in[i].num_placements > 0 && usage < UKIND_END_PLACE) {
asset_id ofs = 0; asset_id ofs = 0;
if (item_get_place_directional(item_id) && in[i].num_placements >= 2) { if (item_get_place_directional(item_id) && in[i].num_placements >= 2) {
@ -289,13 +305,18 @@ void UseItem(ecs_iter_t *it) {
for (size_t j = 0; j < in[i].num_placements; j++) { for (size_t j = 0; j < in[i].num_placements; j++) {
Position pos = {.x = in[i].placements_x[j], .y = in[i].placements_y[j]}; Position pos = {.x = in[i].placements_x[j], .y = in[i].placements_y[j]};
item_use(it->world, item, pos, ofs); item_use(it->world, item_ent, item, pos, ofs);
} }
in[i].num_placements = 0; in[i].num_placements = 0;
} }
entity_wake(it->entities[i]); entity_wake(it->entities[i]);
if (item->quantity == 0) {
item_despawn(item_ent);
inv[i].items[in[i].selected_item] = 0;
}
} }
} }
@ -318,11 +339,13 @@ void HarvestIntoContainers(ecs_iter_t *it) {
// NOTE(zaklaus): find any item // NOTE(zaklaus): find any item
size_t ents_count; size_t ents_count;
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 0); int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 0);
bool picked = false;
for (size_t j = 0; j < ents_count; j++) { for (size_t j = 0; j < ents_count; j++) {
ItemDrop *drop = 0; Item *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) { if ((drop = ecs_get_mut_if(it->world, ents[j], Item))) {
const Position *p2 = ecs_get(it->world, ents[j], Position); Position *p2 = ecs_get_mut(it->world, ents[j], Position);
uint64_t ent_id = ents[j];
float dx = p2->x - p[i].x; float dx = p2->x - p[i].x;
float dy = p2->y - p[i].y; float dy = p2->y - p[i].y;
@ -330,23 +353,32 @@ void HarvestIntoContainers(ecs_iter_t *it) {
if (range <= game_rules.item_pick_radius) { if (range <= game_rules.item_pick_radius) {
uint16_t drop_id = item_find(drop->kind); uint16_t drop_id = item_find(drop->kind);
for (size_t k = 0; k < ITEMS_CONTAINER_SIZE; k += 1) { for (size_t k = 0; k < ITEMS_CONTAINER_SIZE; k += 1) {
ItemDrop *item = &in->items[k]; uint64_t item_slot_ent = in[i].items[k];
uint16_t item_id = item_find(item->kind); Item *item = item_get_data(item_slot_ent);
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)) { uint16_t item_id = item ? item_find(item->kind) : 0;
uint32_t picked_count = zpl_max(0, drop->quantity); if (!item || (item_id != ASSET_INVALID && (item->kind == drop->kind && item->durability == drop->durability) && item->quantity < item_max_quantity(drop_id))) {
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity); if (item) {
item->quantity += picked_count; uint32_t picked_count = zpl_max(0, drop->quantity);
drop->quantity -= picked_count; picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
item->kind = drop->kind; item->quantity += picked_count;
entity_wake(ents[j]); drop->quantity -= picked_count;
entity_wake(it->entities[i]);
if (drop->quantity == 0) if (drop->quantity == 0) {
item_despawn(ents[j]); item_despawn(ent_id);
}
} else if (!world_entity_valid(item_slot_ent)) {
entity_wake(ent_id);
item_show(ent_id, false);
in[i].items[k] = ent_id;
}
entity_wake(it->entities[i]);
picked = true;
break;
} }
} }
} }
} }
if (picked) break;
} }
} }
} }

View File

@ -218,7 +218,7 @@ void SystemsImport(ecs_world_t *ecs) {
ECS_SYSTEM(ecs, UseItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle); ECS_SYSTEM(ecs, UseItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
ECS_SYSTEM(ecs, InspectContainers, EcsPostUpdate, components.Input, !components.IsInVehicle); ECS_SYSTEM(ecs, InspectContainers, EcsPostUpdate, components.Input, !components.IsInVehicle);
ECS_SYSTEM(ecs, HarvestIntoContainers, EcsPostUpdate, components.ItemContainer, components.Position); ECS_SYSTEM(ecs, HarvestIntoContainers, EcsPostUpdate, components.ItemContainer, components.Position);
ECS_SYSTEM(ecs, FurnaceCook, EcsPostUpdate, components.ItemContainer, components.Furnace, components.Position); ECS_SYSTEM(ecs, FurnaceCook, EcsPostUpdate, components.ItemContainer, components.Furnace, components.Position, components.Device);
ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input); ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input);

View File

@ -26,6 +26,7 @@ static inline asset_id item_fix_kind(asset_id id) {
void item_show(uint64_t ent, bool show) { void item_show(uint64_t ent, bool show) {
Classify *c = ecs_get_mut(world_ecs(), ent, Classify); Classify *c = ecs_get_mut(world_ecs(), ent, Classify);
librg_entity_visibility_global_set(world_tracker(), ent, show ? LIBRG_VISIBLITY_DEFAULT : LIBRG_VISIBLITY_NEVER);
c->id = show ? EKIND_ITEM : EKIND_SERVER; c->id = show ? EKIND_ITEM : EKIND_SERVER;
} }
@ -37,8 +38,25 @@ uint64_t item_spawn(asset_id kind, uint32_t qty) {
.kind = item_fix_kind(kind), .kind = item_fix_kind(kind),
.quantity = qty, .quantity = qty,
.merger_time = 0, .merger_time = 0,
.durability = 1.0f,
}; };
item_desc *it = &items[item_find(kind)];
switch (it->attachment) {
case UDATA_FUEL: {
Fuel *f = ecs_get_mut(world_ecs(), e, Fuel);
f->burn_time = it->fuel.burn_time;
} break;
case UDATA_INGREDIENT: {
Ingredient *i = ecs_get_mut(world_ecs(), e, Ingredient);
i->producer = it->ingredient.producer;
i->product = it->ingredient.product;
i->additional_ingredient = it->ingredient.additional_ingredient;
} break;
default: break;
}
return (uint64_t)e; return (uint64_t)e;
} }
@ -51,15 +69,22 @@ item_id item_find(asset_id kind) {
} }
Item *item_get_data(uint64_t ent) { Item *item_get_data(uint64_t ent) {
return ecs_get_mut(world_ecs(), ent, Item); if (!world_entity_valid(ent)) return NULL;
// if (ecs_get(world_ecs(), ent, ItemAlreadyEdited)) return NULL;
// ecs_add(world_ecs(), ent, ItemAlreadyEdited);
return ecs_get_mut_if(world_ecs(), ent, Item);
} }
void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) { const Item *item_get_data_const(uint64_t ent) {
if (!world_entity_valid(ent)) return NULL;
return ecs_get(world_ecs(), ent, Item);
}
void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t udata) {
(void)ecs; (void)ecs;
Item *d = item_get_data(it->ent); if (e == 0) return;
uint16_t it_id = d->kind; uint16_t it_id = item_find(it->kind);
item_desc *desc = &items[it_id]; item_desc *desc = &items[it_id];
if (it->ent == 0) return;
switch (item_get_usage(it_id)) { switch (item_get_usage(it_id)) {
case UKIND_HOLD: /* NOOP */ break; case UKIND_HOLD: /* NOOP */ break;
case UKIND_PLACE:{ case UKIND_PLACE:{
@ -71,7 +96,7 @@ void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) {
// NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it // NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it
if (item_asset_id == it_id) { if (item_asset_id == it_id) {
d->quantity++; it->quantity++;
} else { } else {
return; return;
} }
@ -81,7 +106,7 @@ void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) {
return; return;
} }
world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata)); world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata));
d->quantity--; it->quantity--;
}break; }break;
case UKIND_PLACE_ITEM:{ case UKIND_PLACE_ITEM:{
@ -98,7 +123,7 @@ void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) {
ZPL_ASSERT(world_entity_valid(e)); ZPL_ASSERT(world_entity_valid(e));
entity_set_position(e, p.x, p.y); entity_set_position(e, p.x, p.y);
d->quantity--; it->quantity--;
}break; }break;

View File

@ -17,11 +17,17 @@ typedef enum {
UKIND_PROXY, UKIND_PROXY,
} item_usage; } item_usage;
typedef enum {
UDATA_NONE,
UDATA_FUEL,
UDATA_INGREDIENT,
} item_attachment;
typedef struct { typedef struct {
asset_id kind; asset_id kind;
item_usage usage; item_usage usage;
item_attachment attachment;
uint32_t max_quantity; uint32_t max_quantity;
bool unique;
// NOTE(zaklaus): usage data // NOTE(zaklaus): usage data
union { union {
@ -38,6 +44,18 @@ typedef struct {
asset_id id; asset_id id;
} place_item; } place_item;
}; };
union {
struct {
float burn_time;
} fuel;
struct {
asset_id producer;
asset_id product;
asset_id additional_ingredient;
} ingredient;
};
} item_desc; } item_desc;
typedef uint16_t item_id; typedef uint16_t item_id;
@ -48,15 +66,11 @@ void item_show(uint64_t ent, bool show);
uint64_t item_spawn(asset_id kind, uint32_t qty); uint64_t item_spawn(asset_id kind, uint32_t qty);
void item_despawn(uint64_t id); void item_despawn(uint64_t id);
// NOTE: item ops
void item_pickup(uint64_t ent, uint64_t item);
void item_drop(uint64_t ent, uint64_t item);
void item_merge(uint64_t item1, uint64_t item2);
// NOTE(zaklaus): items // NOTE(zaklaus): items
item_id item_find(asset_id kind); item_id item_find(asset_id kind);
void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata); void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t udata);
Item *item_get_data(uint64_t ent); Item *item_get_data(uint64_t ent);
const Item *item_get_data_const(uint64_t ent);
uint32_t item_max_quantity(item_id id); uint32_t item_max_quantity(item_id id);
item_usage item_get_usage(item_id id); item_usage item_get_usage(item_id id);

View File

@ -4,9 +4,9 @@
static item_desc items[] = { static item_desc items[] = {
{ .kind = 0, .max_quantity = 0, }, { .kind = 0, .max_quantity = 0, },
ITEM_BLOCK(ASSET_DEMO_ICEMAKER, 64, ASSET_WATER), ITEM_INGREDIENT(ASSET_DEMO_ICEMAKER, 64, ASSET_FURNACE, ASSET_BELT, 0),
ITEM_SELF(ASSET_FENCE, 64), ITEM_SELF(ASSET_FENCE, 64),
ITEM_SELF(ASSET_WOOD, 64), ITEM_FUEL(ASSET_WOOD, 64, 15.0f),
ITEM_HOLD(ASSET_TREE, 64), ITEM_HOLD(ASSET_TREE, 64),
ITEM_SELF_DIR(ASSET_BELT, 999), ITEM_SELF_DIR(ASSET_BELT, 999),

View File

@ -4,13 +4,39 @@
{\ {\
.kind = asset,\ .kind = asset,\
.usage = UKIND_HOLD,\ .usage = UKIND_HOLD,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\ .max_quantity = qty,\
} }
#define ITEM_FUEL(asset, qty, fuel_value)\
{\
.kind = asset,\
.usage = UKIND_HOLD,\
.attachment = UDATA_FUEL,\
.max_quantity = qty,\
.fuel = {\
.burn_time = fuel_value\
}\
}
#define ITEM_INGREDIENT(asset, qty, _producer, _product, _additional)\
{\
.kind = asset,\
.usage = UKIND_HOLD,\
.attachment = UDATA_INGREDIENT,\
.max_quantity = qty,\
.ingredient = {\
.producer = _producer,\
.product = _product,\
.additional_ingredient = _additional,\
}\
}
#define ITEM_BLOCK(asset, qty, build_asset)\ #define ITEM_BLOCK(asset, qty, build_asset)\
{\ {\
.kind = asset,\ .kind = asset,\
.usage = UKIND_PLACE,\ .usage = UKIND_PLACE,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\ .max_quantity = qty,\
.place = {\ .place = {\
.kind = build_asset,\ .kind = build_asset,\
@ -21,6 +47,7 @@
{\ {\
.kind = asset,\ .kind = asset,\
.usage = UKIND_PLACE,\ .usage = UKIND_PLACE,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\ .max_quantity = qty,\
.place = {\ .place = {\
.kind = build_asset,\ .kind = build_asset,\
@ -32,6 +59,7 @@
{\ {\
.kind = asset,\ .kind = asset,\
.usage = UKIND_PROXY,\ .usage = UKIND_PROXY,\
.attachment = UDATA_NONE,\
.proxy = {\ .proxy = {\
.id = proxy_id,\ .id = proxy_id,\
}\ }\
@ -41,6 +69,7 @@
{\ {\
.kind = asset,\ .kind = asset,\
.usage = UKIND_PLACE_ITEM,\ .usage = UKIND_PLACE_ITEM,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\ .max_quantity = qty,\
.place_item = {\ .place_item = {\
.id = eid\ .id = eid\

View File

@ -43,7 +43,7 @@ void buildmode_draw(void) {
build_is_deletion_mode = !build_is_deletion_mode; build_is_deletion_mode = !build_is_deletion_mode;
} }
ItemDrop *item = &e->items[e->selected_item]; Item *item = &e->items[e->selected_item];
if (e->has_items && !e->inside_vehicle && item->quantity > 0 && (!is_outside_range || build_is_deletion_mode)) { if (e->has_items && !e->inside_vehicle && item->quantity > 0 && (!is_outside_range || build_is_deletion_mode)) {
item_usage usage = 0; item_usage usage = 0;

View File

@ -4,7 +4,7 @@ typedef struct {
bool item_is_held; bool item_is_held;
uint8_t held_item_idx; uint8_t held_item_idx;
ItemDrop held_item; Item held_item;
bool is_inside; bool is_inside;
bool storage_action; bool storage_action;
@ -44,7 +44,7 @@ void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
{ {
debug_area_status area = check_mouse_area(x, y, 64, 64); debug_area_status area = check_mouse_area(x, y, 64, 64);
Color color = RAYWHITE; Color color = RAYWHITE;
ItemDrop *item = (is_player) ? &e->items[i] : &e->storage_items[i]; Item *item = (is_player) ? &e->items[i] : &e->storage_items[i];
if (area == DAREA_HOVER) { if (area == DAREA_HOVER) {
color = YELLOW; color = YELLOW;

View File

@ -64,12 +64,12 @@ typedef struct entity_view {
// NOTE(zaklaus): inventory // NOTE(zaklaus): inventory
uint8_t has_items; uint8_t has_items;
ItemDrop items[ITEMS_INVENTORY_SIZE]; Item items[ITEMS_INVENTORY_SIZE];
uint8_t selected_item; uint8_t selected_item;
// NOTE(zaklaus): storage interface // NOTE(zaklaus): storage interface
uint8_t has_storage_items; uint8_t has_storage_items;
ItemDrop storage_items[ITEMS_CONTAINER_SIZE]; Item storage_items[ITEMS_CONTAINER_SIZE];
uint8_t storage_selected_item; uint8_t storage_selected_item;
// NOTE(zaklaus): entity picking // NOTE(zaklaus): entity picking

View File

@ -62,7 +62,7 @@ void predict_receive_update(entity_view *d, entity_view *data) {
data->tran_time = d->tran_time; data->tran_time = d->tran_time;
} }
#define ENTITY_DO_LERP_SP 1 #define ENTITY_DO_LERP_SP 0
void lerp_entity_positions(uint64_t key, entity_view *data) { void lerp_entity_positions(uint64_t key, entity_view *data) {
(void)key; (void)key;

View File

@ -56,8 +56,8 @@ entity_view *world_build_entity_view(int64_t e) {
view.heading = veh->heading; view.heading = veh->heading;
} }
if (ecs_get(world_ecs(), e, ItemDrop)) { if (ecs_get(world_ecs(), e, Item)) {
ItemDrop const* dr = ecs_get(world_ecs(), e, ItemDrop); Item const* dr = ecs_get(world_ecs(), e, Item);
view.asset = dr->kind; view.asset = dr->kind;
view.quantity = dr->quantity; view.quantity = dr->quantity;
} }
@ -74,7 +74,8 @@ entity_view *world_build_entity_view(int64_t e) {
view.has_items = true; view.has_items = true;
for (int i = 0; i < ITEMS_INVENTORY_SIZE; i += 1) { for (int i = 0; i < ITEMS_INVENTORY_SIZE; i += 1) {
view.items[i] = inv->items[i]; const Item *it = ecs_get(world_ecs(), inv->items[i], Item);
view.items[i] = it ? *it : (Item){0};
} }
const Input *in = ecs_get(world_ecs(), e, Input); const Input *in = ecs_get(world_ecs(), e, Input);
@ -89,7 +90,8 @@ entity_view *world_build_entity_view(int64_t e) {
view.has_storage_items = true; view.has_storage_items = true;
for (int i = 0; i < ITEMS_CONTAINER_SIZE; i += 1) { for (int i = 0; i < ITEMS_CONTAINER_SIZE; i += 1) {
view.storage_items[i] = ic->items[i]; const Item *it = ecs_get(world_ecs(), ic->items[i], Item);
view.storage_items[i] = it ? *it : (Item){0};
} }
view.storage_selected_item = in->storage_selected_item; view.storage_selected_item = in->storage_selected_item;
@ -590,7 +592,6 @@ int64_t *world_chunk_query_entities(int64_t e, size_t *ents_len, int8_t radius)
ZPL_ASSERT_NOT_NULL(ents_len); ZPL_ASSERT_NOT_NULL(ents_len);
static int64_t ents[UINT16_MAX]; static int64_t ents[UINT16_MAX];
*ents_len = UINT16_MAX; *ents_len = UINT16_MAX;
librg_entity_radius_set(world.tracker, e, radius);
librg_world_query(world.tracker, e, radius, ents, ents_len); librg_world_query(world.tracker, e, radius, ents, ents_len);
return ents; return ents;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff