2022-09-29 14:16:06 +00:00
|
|
|
#include "models/items.h"
|
|
|
|
#include "models/entity.h"
|
2022-09-27 12:56:48 +00:00
|
|
|
#include "world/entity_view.h"
|
2021-08-25 21:36:20 +00:00
|
|
|
#include "world/world.h"
|
2021-08-30 15:50:05 +00:00
|
|
|
#include "world/blocks.h"
|
2021-08-25 21:36:20 +00:00
|
|
|
|
2022-09-29 14:16:06 +00:00
|
|
|
#include "models/components.h"
|
2021-08-25 21:36:20 +00:00
|
|
|
|
2021-08-30 15:50:05 +00:00
|
|
|
#include "zpl.h"
|
|
|
|
|
|
|
|
#include "items_list.c"
|
2022-09-27 15:22:13 +00:00
|
|
|
#define ITEMS_COUNT (sizeof(items)/sizeof(item_desc))
|
2021-08-30 15:50:05 +00:00
|
|
|
|
2021-11-03 18:09:19 +00:00
|
|
|
static inline item_id item_resolve_proxy(item_id id) {
|
2022-09-27 15:22:13 +00:00
|
|
|
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
|
2021-11-03 13:34:32 +00:00
|
|
|
item_usage usage = items[id].usage;
|
|
|
|
if (usage == UKIND_PROXY) {
|
|
|
|
return item_find(items[id].proxy.id);
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline asset_id item_fix_kind(asset_id id) {
|
|
|
|
return items[item_find(id)].kind;
|
|
|
|
}
|
|
|
|
|
2022-09-28 05:29:32 +00:00
|
|
|
void item_show(uint64_t ent, bool show) {
|
|
|
|
Classify *c = ecs_get_mut(world_ecs(), ent, Classify);
|
2022-09-28 13:17:33 +00:00
|
|
|
librg_entity_visibility_global_set(world_tracker(), ent, show ? LIBRG_VISIBLITY_DEFAULT : LIBRG_VISIBLITY_NEVER);
|
2022-09-28 05:29:32 +00:00
|
|
|
c->id = show ? EKIND_ITEM : EKIND_SERVER;
|
|
|
|
}
|
|
|
|
|
2021-11-02 10:48:32 +00:00
|
|
|
uint64_t item_spawn(asset_id kind, uint32_t qty) {
|
2021-08-25 21:36:20 +00:00
|
|
|
ecs_entity_t e = entity_spawn(EKIND_ITEM);
|
2022-09-12 07:08:22 +00:00
|
|
|
|
2022-09-28 05:29:32 +00:00
|
|
|
Item *d = ecs_get_mut(world_ecs(), e, Item);
|
|
|
|
*d = (Item){
|
2021-11-03 13:34:32 +00:00
|
|
|
.kind = item_fix_kind(kind),
|
2021-08-25 21:36:20 +00:00
|
|
|
.quantity = qty,
|
2021-09-09 07:46:22 +00:00
|
|
|
.merger_time = 0,
|
2022-09-28 13:17:33 +00:00
|
|
|
.durability = 1.0f,
|
2021-08-25 21:36:20 +00:00
|
|
|
};
|
2022-09-12 07:08:22 +00:00
|
|
|
|
2022-09-28 13:17:33 +00:00
|
|
|
item_desc *it = &items[item_find(kind)];
|
|
|
|
|
|
|
|
switch (it->attachment) {
|
2022-09-29 15:35:43 +00:00
|
|
|
case UDATA_ENERGY_SOURCE: {
|
|
|
|
EnergySource *f = ecs_get_mut(world_ecs(), e, EnergySource);
|
|
|
|
*f = (EnergySource){
|
|
|
|
.kind = it->energy_source.producer,
|
|
|
|
.energy_level = it->energy_source.energy_level,
|
|
|
|
};
|
2022-09-28 13:17:33 +00:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
2021-08-25 21:36:20 +00:00
|
|
|
return (uint64_t)e;
|
|
|
|
}
|
|
|
|
|
2021-11-03 18:09:19 +00:00
|
|
|
item_id item_find(asset_id kind) {
|
2022-09-27 15:22:13 +00:00
|
|
|
for (item_id i=0; i<ITEMS_COUNT; i++) {
|
2021-08-30 15:50:05 +00:00
|
|
|
if (items[i].kind == kind)
|
2021-11-02 17:58:55 +00:00
|
|
|
return item_resolve_proxy(i);
|
2021-08-30 15:50:05 +00:00
|
|
|
}
|
2021-11-02 10:48:32 +00:00
|
|
|
return ASSET_INVALID;
|
2021-08-30 15:50:05 +00:00
|
|
|
}
|
|
|
|
|
2022-09-28 05:29:32 +00:00
|
|
|
Item *item_get_data(uint64_t ent) {
|
2022-09-28 13:17:33 +00:00
|
|
|
if (!world_entity_valid(ent)) return NULL;
|
|
|
|
// if (ecs_get(world_ecs(), ent, ItemAlreadyEdited)) return NULL;
|
|
|
|
// ecs_add(world_ecs(), ent, ItemAlreadyEdited);
|
2022-09-28 17:10:40 +00:00
|
|
|
return ecs_get_mut_if_ex(world_ecs(), ent, Item);
|
2022-09-28 13:17:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Item *item_get_data_const(uint64_t ent) {
|
|
|
|
if (!world_entity_valid(ent)) return NULL;
|
|
|
|
return ecs_get(world_ecs(), ent, Item);
|
2022-09-28 05:29:32 +00:00
|
|
|
}
|
|
|
|
|
2022-09-28 13:17:33 +00:00
|
|
|
void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t udata) {
|
2021-08-30 15:50:05 +00:00
|
|
|
(void)ecs;
|
2022-09-28 13:17:33 +00:00
|
|
|
if (e == 0) return;
|
|
|
|
uint16_t it_id = item_find(it->kind);
|
2021-11-03 18:09:19 +00:00
|
|
|
item_desc *desc = &items[it_id];
|
|
|
|
switch (item_get_usage(it_id)) {
|
2021-11-02 17:09:54 +00:00
|
|
|
case UKIND_HOLD: /* NOOP */ break;
|
2021-08-30 15:50:05 +00:00
|
|
|
case UKIND_PLACE:{
|
|
|
|
world_block_lookup l = world_block_from_realpos(p.x, p.y);
|
2021-11-03 18:04:34 +00:00
|
|
|
if (l.is_outer && l.bid > 0) {
|
|
|
|
asset_id item_asset = blocks_get_asset(l.bid);
|
2021-11-03 18:09:19 +00:00
|
|
|
item_id item_asset_id = item_find(item_asset);
|
2021-11-03 15:41:42 +00:00
|
|
|
if (item_asset_id == ASSET_INVALID) return;
|
2022-09-12 07:08:22 +00:00
|
|
|
|
2021-11-03 16:16:35 +00:00
|
|
|
// NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it
|
2021-11-03 18:09:19 +00:00
|
|
|
if (item_asset_id == it_id) {
|
2022-09-28 13:17:33 +00:00
|
|
|
it->quantity++;
|
2021-11-03 16:17:48 +00:00
|
|
|
} else {
|
|
|
|
return;
|
2021-11-03 16:16:35 +00:00
|
|
|
}
|
2022-08-01 09:19:52 +00:00
|
|
|
}
|
2021-11-03 16:48:56 +00:00
|
|
|
// NOTE(zaklaus): This is an inner layer block, we can't build over it if it has a collision!
|
2021-11-03 18:04:34 +00:00
|
|
|
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
|
2021-11-03 16:48:56 +00:00
|
|
|
return;
|
2022-08-01 09:19:52 +00:00
|
|
|
}
|
2021-11-03 15:29:45 +00:00
|
|
|
world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata));
|
2022-09-28 13:17:33 +00:00
|
|
|
it->quantity--;
|
2021-08-30 15:50:05 +00:00
|
|
|
}break;
|
2022-09-12 07:08:22 +00:00
|
|
|
|
2022-08-09 14:46:23 +00:00
|
|
|
case UKIND_PLACE_ITEM:{
|
|
|
|
world_block_lookup l = world_block_from_realpos(p.x, p.y);
|
|
|
|
if (l.is_outer && l.bid > 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// NOTE(zaklaus): This is an inner layer block, we can't build over it if it has a collision!
|
|
|
|
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
|
|
|
|
return;
|
|
|
|
}
|
2022-09-12 07:08:22 +00:00
|
|
|
|
2022-08-13 06:43:15 +00:00
|
|
|
ecs_entity_t e = entity_spawn_id(desc->place_item.id);
|
2022-08-09 14:46:23 +00:00
|
|
|
ZPL_ASSERT(world_entity_valid(e));
|
2022-09-14 08:02:35 +00:00
|
|
|
entity_set_position(e, p.x, p.y);
|
2022-09-12 07:08:22 +00:00
|
|
|
|
2022-09-28 13:17:33 +00:00
|
|
|
it->quantity--;
|
2022-08-09 14:46:23 +00:00
|
|
|
}break;
|
2022-09-12 07:08:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
case UKIND_DELETE:
|
|
|
|
case UKIND_END_PLACE:
|
|
|
|
case UKIND_PROXY:
|
|
|
|
break;
|
2021-08-30 15:50:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-25 21:36:20 +00:00
|
|
|
void item_despawn(uint64_t id) {
|
|
|
|
entity_despawn(id);
|
|
|
|
}
|
|
|
|
|
2021-11-03 18:09:19 +00:00
|
|
|
uint32_t item_max_quantity(item_id id) {
|
2022-09-27 15:22:13 +00:00
|
|
|
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
|
2021-08-30 15:50:05 +00:00
|
|
|
return items[id].max_quantity;
|
|
|
|
}
|
|
|
|
|
2021-11-03 18:09:19 +00:00
|
|
|
item_usage item_get_usage(item_id id) {
|
2022-09-27 15:22:13 +00:00
|
|
|
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
|
2021-08-30 15:50:05 +00:00
|
|
|
return items[id].usage;
|
2021-11-02 17:58:55 +00:00
|
|
|
}
|
|
|
|
|
2021-11-03 18:09:19 +00:00
|
|
|
bool item_get_place_directional(item_id id) {
|
2022-09-27 15:22:13 +00:00
|
|
|
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
|
2021-11-02 17:58:55 +00:00
|
|
|
return items[id].place.directional;
|
2022-07-31 14:34:47 +00:00
|
|
|
}
|