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,
.demo_npc_move_speed = 500,
.demo_npc_steer_speed = 300,
.furnace_cook_time = 5.0f,
.furnace_cook_time = 1.f,
.item_pick_radius = 25.0f,
.item_merger_radius = 75.0f,
.item_attract_radius = 75.0f,

View File

@ -49,7 +49,7 @@ ActSpawnChest(void) {
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;
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(IsInVehicle);
ECS_COMPONENT_DECLARE(Item);
ECS_COMPONENT_DECLARE(ItemAlreadyEdited);
ECS_COMPONENT_DECLARE(Inventory);
ECS_COMPONENT_DECLARE(ItemContainer);
ECS_COMPONENT_DECLARE(Furnace);
ECS_COMPONENT_DECLARE(Fuel);
ECS_COMPONENT_DECLARE(Ingredient);
ECS_COMPONENT_DECLARE(Device);
ECS_COMPONENT_DECLARE(DemoNPC);
ECS_COMPONENT_DECLARE(StreamInfo);
@ -34,9 +37,12 @@ void ComponentsImport(ecs_world_t *ecs) {
ECS_COMPONENT_DEFINE(ecs, Vehicle);
ECS_COMPONENT_DEFINE(ecs, IsInVehicle);
ECS_COMPONENT_DEFINE(ecs, Item);
ECS_COMPONENT_DEFINE(ecs, ItemAlreadyEdited);
ECS_COMPONENT_DEFINE(ecs, Inventory);
ECS_COMPONENT_DEFINE(ecs, ItemContainer);
ECS_COMPONENT_DEFINE(ecs, Furnace);
ECS_COMPONENT_DEFINE(ecs, Fuel);
ECS_COMPONENT_DEFINE(ecs, Ingredient);
ECS_COMPONENT_DEFINE(ecs, Device);
ECS_COMPONENT_DEFINE(ecs, DemoNPC);
ECS_COMPONENT_DEFINE(ecs, StreamInfo);

View File

@ -1,5 +1,6 @@
#pragma once
#include "flecs/flecs.h"
#include "gen/assets.h"
#ifndef ecs_get_mut_if
#define ecs_get_mut_if(world, entity, component)\
@ -100,12 +101,17 @@ typedef struct {
uint16_t kind;
uint32_t quantity;
float merger_time;
float durability; // 1.0 - 0.0 (0.0 = broken), we can only ever merge items of the same durability
} Item;
typedef struct {
char _unused;
} ItemAlreadyEdited;
typedef struct {
// 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.
ecs_entity_t items[ITEMS_CONTAINER_SIZE];
ecs_entity_t items[ITEMS_INVENTORY_SIZE];
float pickup_time;
} Inventory;
@ -114,18 +120,21 @@ typedef struct {
} ItemContainer;
typedef struct {
ecs_entity_t processed_item;
asset_id processed_item;
float cook_time;
float burn_time;
} Furnace;
// typedef struct {
// float burn_time;
// } Fuel;
typedef struct {
asset_id kind;
float burn_time;
} Fuel;
// typedef struct {
// asset_id converted_kind;
// } FuelTank;
typedef struct {
asset_id producer;
asset_id additional_ingredient; // optional - can specify additional item we need in the container to craft this item
asset_id product;
} Ingredient;
typedef struct {
uint16_t asset;
@ -150,9 +159,12 @@ extern ECS_COMPONENT_DECLARE(Classify);
extern ECS_COMPONENT_DECLARE(Vehicle);
extern ECS_COMPONENT_DECLARE(IsInVehicle);
extern ECS_COMPONENT_DECLARE(Item);
extern ECS_COMPONENT_DECLARE(ItemAlreadyEdited);
extern ECS_COMPONENT_DECLARE(Inventory);
extern ECS_COMPONENT_DECLARE(ItemContainer);
extern ECS_COMPONENT_DECLARE(Furnace);
extern ECS_COMPONENT_DECLARE(Fuel);
extern ECS_COMPONENT_DECLARE(Ingredient);
extern ECS_COMPONENT_DECLARE(Device);
extern ECS_COMPONENT_DECLARE(DemoNPC);
extern ECS_COMPONENT_DECLARE(StreamInfo);

View File

@ -2,33 +2,42 @@ void FurnaceCook(ecs_iter_t *it) {
ItemContainer *storage = ecs_field(it, ItemContainer, 1);
Furnace *furnace = ecs_field(it, Furnace, 2);
Position *p = ecs_field(it, Position, 3);
Device *d = ecs_field(it, Device, 4);
for (int i = 0; i < it->count; i++) {
for (int j = 0; j < ITEMS_CONTAINER_SIZE; j++) {
if (storage[i].items[j].kind == ASSET_COAL) {
// furnace[i].fuel_level += itemdb_get(storage[i].items[j].uuid, ITEMDB_FUEL_LEVEL);
// furnace[i].fuel_level = zpl_clamp(furnace[i].fuel_level + 0.8f, 0.0f, 1.0f);
storage[i].items[j].quantity--;
if (storage[i].items[j].quantity == 0) {
storage[i].items[j] = (ItemSlot){0};
ecs_entity_t item_slot_ent = storage[i].items[j];
Item *item = item_get_data(item_slot_ent);
const Fuel *fuel = 0;
if ((fuel = ecs_get(it->world, item_slot_ent, Fuel))) {
if (fuel->kind == d->asset) {
furnace[i].burn_time += fuel->kind;
item_despawn(item_slot_ent);
storage[i].items[j] = 0;
}
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].processed_item.kind > 0) {
uint64_t e = item_spawn(furnace[i].processed_item.kind, 1);
if (furnace[i].processed_item > 0) {
uint64_t e = item_spawn(furnace[i].processed_item, 1);
entity_set_position(e, p[i].x, p[i].y);
furnace[i].processed_item.kind = 0;
furnace[i].processed_item = 0;
} else {
if (storage[i].items[j].kind == ASSET_DEMO_ICEMAKER) {
furnace[i].processed_item.kind = ASSET_BELT;
storage[i].items[j].quantity--;
if (storage[i].items[j].quantity == 0) {
storage[i].items[j] = (ItemSlot){0};
const Ingredient *ing = 0;
if ((ing = ecs_get(it->world, item_slot_ent, Ingredient))) {
if (ing->producer == d->asset) {
furnace[i].processed_item = ing->product;
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;
size_t ents_count;
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++) {
Item *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], Item))) {
Position *p2 = ecs_get_mut(it->world, ents[j], Position);
Velocity *v2 = ecs_get_mut(it->world, ents[j], Velocity);
uint64_t ent_id = ents[j];
if ((drop = ecs_get_mut_if(it->world, ent_id, Item))) {
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 dy = p2->y - p[i].y;
@ -21,23 +23,25 @@ void PickItem(ecs_iter_t *it) {
if (range <= game_rules.item_pick_radius) {
uint16_t drop_id = item_find(drop->kind);
for (size_t k = 0; k < ITEMS_INVENTORY_SIZE; k += 1) {
ItemSlot *item_slot = &inv[i].items[k];
Item *item = item_get_data(item_slot->ent);
uint16_t item_id = item_find(item->kind);
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)
&& (item_slot->ent == 0 || item_slot->ent == ents[j])) {
uint32_t picked_count = zpl_max(0, drop->quantity);
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
item_slot->ent = ents[j];
item->quantity += picked_count;
drop->quantity -= picked_count;
item->kind = drop->kind;
entity_wake(ents[j]);
ecs_entity_t item_slot_ent = inv[i].items[k];
Item *item = item_get_data(item_slot_ent);
uint16_t item_id = item ? item_find(item->kind) : 0;
if (!item || (item_id != ASSET_INVALID && (item->kind == drop->kind && item->durability == drop->durability) && item->quantity < item_max_quantity(drop_id))) {
if (item) {
uint32_t picked_count = zpl_max(0, drop->quantity);
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
item->quantity += picked_count;
drop->quantity -= picked_count;
item->kind = drop->kind;
if (drop->quantity == 0)
item_show(ents[j], false);
item_slot->ent = ents[j];
if (drop->quantity == 0)
item_despawn(ent_id);
} else if (!world_entity_valid(item_slot_ent)) {
entity_wake(ent_id);
item_show(ent_id, false);
inv[i].items[k] = ent_id;
}
picked = true;
break;
}
}
@ -46,6 +50,8 @@ void PickItem(ecs_iter_t *it) {
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++) {
if (!in[i].drop) continue;
ItemSlot *items = inv[i].items;
ecs_entity_t *items = inv[i].items;
if (in[i].storage_action){
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];
Item *item = item_get_data(item_slot->ent);
uint8_t slot_id = in[i].storage_action ? in[i].storage_selected_item : in[i].selected_item;
ecs_entity_t item_slot_ent = items[slot_id];
Item *item = item_get_data(item_slot_ent);
if (!item || item->quantity <= 0)
continue;
@ -83,72 +90,67 @@ void DropItem(ecs_iter_t *it) {
if (in[i].sprint) {
dropped_count /= 2;
} else if (in[i].ctrl) {
dropped_count = dropped_count > 0 ? 1 : 0;
dropped_count = item->quantity-1;
}
if (dropped_count == 0)
continue;
ecs_entity_t te = item_slot->ent;
item_show(item_slot->ent, true);
item->quantity -= dropped_count;
item_show(item_slot_ent, true);
ItemDrop *d = ecs_get_mut(world_ecs(), te, ItemDrop);
*d = (ItemDrop){
.kind = item->kind,
.quantity = dropped_count,
.merger_time = game_time() + game_rules.item_drop_merger_time,
};
Position *ipos = ecs_get_mut(it->world, item_slot_ent, Position);
entity_set_position(item_slot_ent, p[i].x, p[i].y);
Position *ipos = ecs_get_mut(it->world, te, Position);
*ipos = p[i];
Velocity *v = ecs_get_mut(it->world, te, Velocity);
Velocity *v = ecs_get_mut(it->world, item_slot_ent, Velocity);
v->x = in[i].mx * 800.0f;
v->y = in[i].my * 800.0f;
inv[i].pickup_time = game_time() + game_rules.item_drop_pickup_time;
in[i].drop = false;
items[slot_id] = 0;
if (item->quantity == 0) {
item->kind = 0;
if (item->quantity - dropped_count > 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) {
Position *p = ecs_field(it, Position, 1);
ItemDrop *id = ecs_field(it, ItemDrop, 2);
// void MergeItems(ecs_iter_t *it) {
// Position *p = ecs_field(it, Position, 1);
// ItemDrop *id = ecs_field(it, ItemDrop, 2);
for (int i = 0; i < it->count; i += 1) {
ItemDrop *item = &id[i];
// for (int i = 0; i < it->count; i += 1) {
// ItemDrop *item = &id[i];
if (item->merger_time < game_time())
continue;
// if (item->merger_time < game_time())
// continue;
size_t ents_count;
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 1);
// size_t ents_count;
// int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 1);
for (size_t j = 0; j < ents_count; j++) {
ItemDrop *drop = 0;
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)
continue;
// for (size_t j = 0; j < ents_count; j++) {
// ItemDrop *drop = 0;
// 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)
// 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 dy = p2->y - (p[i].y);
float range = zpl_sqrt(dx*dx + dy*dy);
if (range <= game_rules.item_merger_radius) {
drop->quantity += item->quantity;
item_despawn(it->entities[i]);
break;
}
}
}
}
}
// float dx = p2->x - (p[i].x);
// float dy = p2->y - (p[i].y);
// float range = zpl_sqrt(dx*dx + dy*dy);
// if (range <= game_rules.item_merger_radius) {
// drop->quantity += item->quantity;
// item_despawn(it->entities[i]);
// break;
// }
// }
// }
// }
// }
void SwapItems(ecs_iter_t *it) {
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++) {
if (!in[i].swap) continue;
ItemDrop *items = inv[i].items;
ecs_entity_t *items = inv[i].items;
if (in[i].storage_action){
if (world_entity_valid(in[i].storage_ent)){
@ -172,40 +174,49 @@ void SwapItems(ecs_iter_t *it) {
}
}
ItemDrop *to = 0;
ItemDrop *from = 0;
ecs_entity_t *from_ent = 0;
ecs_entity_t *to_ent = 0;
Item *to = 0;
Item *from = 0;
if (in[i].swap_storage){
in[i].swap_storage = false;
if (in[i].storage_action){
from = &inv[i].items[in[i].swap_from];
to = &items[in[i].swap_to];
from_ent = &inv[i].items[in[i].swap_from];
to_ent = &items[in[i].swap_to];
from = item_get_data(*from_ent);
to = item_get_data(*to_ent);
}else{
if (world_entity_valid(in[i].storage_ent)){
ItemContainer *ic = 0;
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{
continue;
}
}else{
continue;
}
to = &items[in[i].swap_to];
to_ent = &items[in[i].swap_to];
to = item_get_data(*to_ent);
}
}else{
from = &items[in[i].swap_from];
to = &items[in[i].swap_to];
from_ent = &items[in[i].swap_from];
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
} else if (to->kind == from->kind && to->quantity > 0) {
} else if (to_kind == from->kind && to->quantity > 0) {
uint32_t swapped_count = from->quantity;
if (in[i].sprint) {
swapped_count /= 2;
@ -216,24 +227,28 @@ void SwapItems(ecs_iter_t *it) {
to->quantity += swapped_count;
from->quantity -= swapped_count;
if (swapped_count == 0) {
ItemDrop tmp = *to;
*to = *from;
*from = tmp;
if (from->quantity == 0) {
item_despawn(*from_ent);
*from_ent = 0;
}
} 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
uint32_t split_count = from->quantity / 2;
if (in[i].ctrl) {
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;
to->kind = from->kind;
} else {
ItemDrop tmp = *to;
*to = *from;
*from = tmp;
ecs_entity_t tmp = *to_ent;
*to_ent = *from_ent;
*from_ent = tmp;
}
in[i].swap = false;
@ -252,12 +267,13 @@ void UseItem(ecs_iter_t *it) {
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;
item_usage usage = UKIND_DELETE;
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);
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)
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) {
asset_id ofs = 0;
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++) {
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;
}
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
size_t ents_count;
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++) {
ItemDrop *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
const Position *p2 = ecs_get(it->world, ents[j], Position);
Item *drop = 0;
if ((drop = ecs_get_mut_if(it->world, ents[j], Item))) {
Position *p2 = ecs_get_mut(it->world, ents[j], Position);
uint64_t ent_id = ents[j];
float dx = p2->x - p[i].x;
float dy = p2->y - p[i].y;
@ -330,23 +353,32 @@ void HarvestIntoContainers(ecs_iter_t *it) {
if (range <= game_rules.item_pick_radius) {
uint16_t drop_id = item_find(drop->kind);
for (size_t k = 0; k < ITEMS_CONTAINER_SIZE; k += 1) {
ItemDrop *item = &in->items[k];
uint16_t item_id = item_find(item->kind);
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)) {
uint32_t picked_count = zpl_max(0, drop->quantity);
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
item->quantity += picked_count;
drop->quantity -= picked_count;
item->kind = drop->kind;
entity_wake(ents[j]);
entity_wake(it->entities[i]);
uint64_t item_slot_ent = in[i].items[k];
Item *item = item_get_data(item_slot_ent);
uint16_t item_id = item ? item_find(item->kind) : 0;
if (!item || (item_id != ASSET_INVALID && (item->kind == drop->kind && item->durability == drop->durability) && item->quantity < item_max_quantity(drop_id))) {
if (item) {
uint32_t picked_count = zpl_max(0, drop->quantity);
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
item->quantity += picked_count;
drop->quantity -= picked_count;
if (drop->quantity == 0)
item_despawn(ents[j]);
if (drop->quantity == 0) {
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, InspectContainers, EcsPostUpdate, components.Input, !components.IsInVehicle);
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);

View File

@ -26,6 +26,7 @@ static inline asset_id item_fix_kind(asset_id id) {
void item_show(uint64_t ent, bool show) {
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;
}
@ -37,8 +38,25 @@ uint64_t item_spawn(asset_id kind, uint32_t qty) {
.kind = item_fix_kind(kind),
.quantity = qty,
.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;
}
@ -51,15 +69,22 @@ item_id item_find(asset_id kind) {
}
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;
Item *d = item_get_data(it->ent);
uint16_t it_id = d->kind;
if (e == 0) return;
uint16_t it_id = item_find(it->kind);
item_desc *desc = &items[it_id];
if (it->ent == 0) return;
switch (item_get_usage(it_id)) {
case UKIND_HOLD: /* NOOP */ break;
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
if (item_asset_id == it_id) {
d->quantity++;
it->quantity++;
} else {
return;
}
@ -81,7 +106,7 @@ void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) {
return;
}
world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata));
d->quantity--;
it->quantity--;
}break;
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));
entity_set_position(e, p.x, p.y);
d->quantity--;
it->quantity--;
}break;

View File

@ -17,11 +17,17 @@ typedef enum {
UKIND_PROXY,
} item_usage;
typedef enum {
UDATA_NONE,
UDATA_FUEL,
UDATA_INGREDIENT,
} item_attachment;
typedef struct {
asset_id kind;
item_usage usage;
item_attachment attachment;
uint32_t max_quantity;
bool unique;
// NOTE(zaklaus): usage data
union {
@ -38,6 +44,18 @@ typedef struct {
asset_id id;
} place_item;
};
union {
struct {
float burn_time;
} fuel;
struct {
asset_id producer;
asset_id product;
asset_id additional_ingredient;
} ingredient;
};
} item_desc;
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);
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
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);
const Item *item_get_data_const(uint64_t ent);
uint32_t item_max_quantity(item_id id);
item_usage item_get_usage(item_id id);

View File

@ -4,9 +4,9 @@
static item_desc items[] = {
{ .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_WOOD, 64),
ITEM_FUEL(ASSET_WOOD, 64, 15.0f),
ITEM_HOLD(ASSET_TREE, 64),
ITEM_SELF_DIR(ASSET_BELT, 999),

View File

@ -4,13 +4,39 @@
{\
.kind = asset,\
.usage = UKIND_HOLD,\
.attachment = UDATA_NONE,\
.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)\
{\
.kind = asset,\
.usage = UKIND_PLACE,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\
.place = {\
.kind = build_asset,\
@ -21,6 +47,7 @@
{\
.kind = asset,\
.usage = UKIND_PLACE,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\
.place = {\
.kind = build_asset,\
@ -32,6 +59,7 @@
{\
.kind = asset,\
.usage = UKIND_PROXY,\
.attachment = UDATA_NONE,\
.proxy = {\
.id = proxy_id,\
}\
@ -41,6 +69,7 @@
{\
.kind = asset,\
.usage = UKIND_PLACE_ITEM,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\
.place_item = {\
.id = eid\

View File

@ -43,7 +43,7 @@ void buildmode_draw(void) {
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)) {
item_usage usage = 0;

View File

@ -4,7 +4,7 @@ typedef struct {
bool item_is_held;
uint8_t held_item_idx;
ItemDrop held_item;
Item held_item;
bool is_inside;
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);
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) {
color = YELLOW;

View File

@ -64,12 +64,12 @@ typedef struct entity_view {
// NOTE(zaklaus): inventory
uint8_t has_items;
ItemDrop items[ITEMS_INVENTORY_SIZE];
Item items[ITEMS_INVENTORY_SIZE];
uint8_t selected_item;
// NOTE(zaklaus): storage interface
uint8_t has_storage_items;
ItemDrop storage_items[ITEMS_CONTAINER_SIZE];
Item storage_items[ITEMS_CONTAINER_SIZE];
uint8_t storage_selected_item;
// 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;
}
#define ENTITY_DO_LERP_SP 1
#define ENTITY_DO_LERP_SP 0
void lerp_entity_positions(uint64_t key, entity_view *data) {
(void)key;

View File

@ -56,8 +56,8 @@ entity_view *world_build_entity_view(int64_t e) {
view.heading = veh->heading;
}
if (ecs_get(world_ecs(), e, ItemDrop)) {
ItemDrop const* dr = ecs_get(world_ecs(), e, ItemDrop);
if (ecs_get(world_ecs(), e, Item)) {
Item const* dr = ecs_get(world_ecs(), e, Item);
view.asset = dr->kind;
view.quantity = dr->quantity;
}
@ -74,7 +74,8 @@ entity_view *world_build_entity_view(int64_t e) {
view.has_items = true;
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);
@ -89,7 +90,8 @@ entity_view *world_build_entity_view(int64_t e) {
view.has_storage_items = true;
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;
@ -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);
static int64_t ents[UINT16_MAX];
*ents_len = UINT16_MAX;
librg_entity_radius_set(world.tracker, e, radius);
librg_world_query(world.tracker, e, radius, ents, ents_len);
return ents;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff