wip craft system automation improvements
parent
80d8620ee1
commit
7ecc5cd0d7
|
@ -20,6 +20,7 @@ add_library(eco2d-foundation STATIC
|
||||||
src/models/prefabs/storage.c
|
src/models/prefabs/storage.c
|
||||||
src/models/prefabs/furnace.c
|
src/models/prefabs/furnace.c
|
||||||
src/models/prefabs/blueprint.c
|
src/models/prefabs/blueprint.c
|
||||||
|
src/models/prefabs/splitter.c
|
||||||
src/models/prefabs/craftbench.c
|
src/models/prefabs/craftbench.c
|
||||||
|
|
||||||
src/pkt/packet.c
|
src/pkt/packet.c
|
||||||
|
|
|
@ -52,6 +52,7 @@ Texture2D texgen_build_sprite_fallback(asset_id id) {
|
||||||
case ASSET_CHEST: return LoadTexEco("chest");
|
case ASSET_CHEST: return LoadTexEco("chest");
|
||||||
case ASSET_FURNACE: return LoadTexEco("furnace-export");
|
case ASSET_FURNACE: return LoadTexEco("furnace-export");
|
||||||
case ASSET_CRAFTBENCH: return LoadTexEco("craftbench");
|
case ASSET_CRAFTBENCH: return LoadTexEco("craftbench");
|
||||||
|
case ASSET_SPLITTER: return LoadTexEco("item_splitter");
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
X(ASSET_PLAYER)\
|
X(ASSET_PLAYER)\
|
||||||
X(ASSET_THING)\
|
X(ASSET_THING)\
|
||||||
X(ASSET_CHEST)\
|
X(ASSET_CHEST)\
|
||||||
|
X(ASSET_SPLITTER)\
|
||||||
X(ASSET_FURNACE)\
|
X(ASSET_FURNACE)\
|
||||||
X(ASSET_CRAFTBENCH)\
|
X(ASSET_CRAFTBENCH)\
|
||||||
X(ASSET_BLUEPRINT_BEGIN)\
|
X(ASSET_BLUEPRINT_BEGIN)\
|
||||||
|
|
|
@ -24,6 +24,7 @@ static asset assets[] = {
|
||||||
ASSET_TEX(ASSET_PLANK),
|
ASSET_TEX(ASSET_PLANK),
|
||||||
ASSET_TEX(ASSET_CHEST),
|
ASSET_TEX(ASSET_CHEST),
|
||||||
ASSET_TEX(ASSET_FURNACE),
|
ASSET_TEX(ASSET_FURNACE),
|
||||||
|
ASSET_TEX(ASSET_SPLITTER),
|
||||||
ASSET_TEX(ASSET_CRAFTBENCH),
|
ASSET_TEX(ASSET_CRAFTBENCH),
|
||||||
ASSET_TEX(ASSET_BLUEPRINT),
|
ASSET_TEX(ASSET_BLUEPRINT),
|
||||||
ASSET_TEX(ASSET_BLUEPRINT_DEMO_HOUSE),
|
ASSET_TEX(ASSET_BLUEPRINT_DEMO_HOUSE),
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "models/prefabs/furnace.h"
|
#include "models/prefabs/furnace.h"
|
||||||
#include "models/prefabs/blueprint.h"
|
#include "models/prefabs/blueprint.h"
|
||||||
#include "models/prefabs/craftbench.h"
|
#include "models/prefabs/craftbench.h"
|
||||||
|
#include "models/prefabs/splitter.h"
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
asset_id id;
|
asset_id id;
|
||||||
|
@ -12,6 +13,7 @@ static struct {
|
||||||
{ .id = ASSET_CHEST, .proc = storage_spawn },
|
{ .id = ASSET_CHEST, .proc = storage_spawn },
|
||||||
{ .id = ASSET_FURNACE, .proc = furnace_spawn },
|
{ .id = ASSET_FURNACE, .proc = furnace_spawn },
|
||||||
{ .id = ASSET_CRAFTBENCH, .proc = craftbench_spawn },
|
{ .id = ASSET_CRAFTBENCH, .proc = craftbench_spawn },
|
||||||
|
{ .id = ASSET_SPLITTER, .proc = splitter_spawn },
|
||||||
{ .id = ASSET_BLUEPRINT, .proc_udata = blueprint_spawn_udata },
|
{ .id = ASSET_BLUEPRINT, .proc_udata = blueprint_spawn_udata },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ static item_desc items[] = {
|
||||||
ITEM_ENT(ASSET_CHEST, 32, ASSET_CHEST),
|
ITEM_ENT(ASSET_CHEST, 32, ASSET_CHEST),
|
||||||
ITEM_ENT(ASSET_CRAFTBENCH, 32, ASSET_CRAFTBENCH),
|
ITEM_ENT(ASSET_CRAFTBENCH, 32, ASSET_CRAFTBENCH),
|
||||||
ITEM_ENT(ASSET_FURNACE, 32, ASSET_FURNACE),
|
ITEM_ENT(ASSET_FURNACE, 32, ASSET_FURNACE),
|
||||||
|
ITEM_ENT(ASSET_SPLITTER, 32, ASSET_SPLITTER),
|
||||||
|
|
||||||
ITEM_HOLD(ASSET_IRON_ORE, 64),
|
ITEM_HOLD(ASSET_IRON_ORE, 64),
|
||||||
ITEM_HOLD(ASSET_IRON_INGOT, 64),
|
ITEM_HOLD(ASSET_IRON_INGOT, 64),
|
||||||
|
|
|
@ -129,11 +129,27 @@ typedef struct {
|
||||||
ecs_entity_t items[ITEMS_CONTAINER_SIZE];
|
ecs_entity_t items[ITEMS_CONTAINER_SIZE];
|
||||||
} ItemContainer;
|
} ItemContainer;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PRODUCER_PUSH_PRODUCT,
|
||||||
|
PRODUCER_PUSH_ANY,
|
||||||
|
PRODUCER_PUSH_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PRODUCER_CRAFT_WAITING,
|
||||||
|
PRODUCER_CRAFT_BUSY,
|
||||||
|
PRODUCER_CRAFT_ENQUEUED,
|
||||||
|
PRODUCER_CRAFT_AUTO,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
asset_id target_item;
|
||||||
asset_id processed_item;
|
asset_id processed_item;
|
||||||
uint32_t processed_item_qty;
|
uint32_t processed_item_qty;
|
||||||
float process_time;
|
float process_time;
|
||||||
float energy_level;
|
float energy_level;
|
||||||
|
uint8_t pending_task;
|
||||||
|
uint8_t push_filter;
|
||||||
} Producer;
|
} Producer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -51,7 +51,7 @@ bool craft_is_reagent_used_in_producer(asset_id reagent, asset_id producer) {
|
||||||
return craft__find_num_recipes_by_reagent(producer, reagent) > 0;
|
return craft__find_num_recipes_by_reagent(producer, reagent) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, uint32_t *quantity) {
|
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id target, uint32_t *quantity) {
|
||||||
ZPL_ASSERT_NOT_NULL(items);
|
ZPL_ASSERT_NOT_NULL(items);
|
||||||
|
|
||||||
for (int i = 0; i < ITEMS_CONTAINER_SIZE; i++) {
|
for (int i = 0; i < ITEMS_CONTAINER_SIZE; i++) {
|
||||||
|
@ -70,6 +70,12 @@ asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, uint32_t *
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target != 0 && rec->product != target) {
|
||||||
|
// NOTE(zaklaus): we were asked to produce a specific product,
|
||||||
|
// however this recipe is not compatible, bail.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t skip_slot=0;
|
uint8_t skip_slot=0;
|
||||||
|
|
||||||
// NOTE(zaklaus): analyse if all the reagents are present
|
// NOTE(zaklaus): analyse if all the reagents are present
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
// NOTE(zaklaus): resolves recipe dependencies and consumes reagents
|
// NOTE(zaklaus): resolves recipe dependencies and consumes reagents
|
||||||
// to enqueue a production of a new item.
|
// to enqueue a production of a new item.
|
||||||
// TODO(zaklaus): "items" is assumed to come from ItemContainer component.
|
// TODO(zaklaus): "items" is assumed to come from ItemContainer component.
|
||||||
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, uint32_t *quantity);
|
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id target, uint32_t *quantity);
|
||||||
|
|
||||||
// NOTE(zaklaus): informs us on whether this product has any byproducts desired.
|
// NOTE(zaklaus): informs us on whether this product has any byproducts desired.
|
||||||
asset_id craft_has_byproducts(asset_id product);
|
asset_id craft_has_byproducts(asset_id product);
|
||||||
|
|
|
@ -14,6 +14,8 @@ uint64_t craftbench_spawn(void) {
|
||||||
Producer *producer = ecs_get_mut(world_ecs(), e, Producer);
|
Producer *producer = ecs_get_mut(world_ecs(), e, Producer);
|
||||||
*producer = (Producer){0};
|
*producer = (Producer){0};
|
||||||
producer->energy_level = 69.0f;
|
producer->energy_level = 69.0f;
|
||||||
|
producer->pending_task = PRODUCER_CRAFT_WAITING;
|
||||||
|
producer->push_filter = PRODUCER_PUSH_NONE;
|
||||||
|
|
||||||
ecs_set(world_ecs(), e, ItemRouter, {1});
|
ecs_set(world_ecs(), e, ItemRouter, {1});
|
||||||
return (uint64_t)e;
|
return (uint64_t)e;
|
||||||
|
|
|
@ -14,6 +14,8 @@ uint64_t furnace_spawn(void) {
|
||||||
Producer *producer = ecs_get_mut(world_ecs(), e, Producer);
|
Producer *producer = ecs_get_mut(world_ecs(), e, Producer);
|
||||||
*producer = (Producer){0};
|
*producer = (Producer){0};
|
||||||
producer->energy_level = 69.0f;
|
producer->energy_level = 69.0f;
|
||||||
|
producer->pending_task = PRODUCER_CRAFT_AUTO;
|
||||||
|
producer->push_filter = PRODUCER_PUSH_ANY;
|
||||||
|
|
||||||
ecs_set(world_ecs(), e, ItemRouter, {1});
|
ecs_set(world_ecs(), e, ItemRouter, {1});
|
||||||
return (uint64_t)e;
|
return (uint64_t)e;
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "splitter.h"
|
||||||
|
#include "models/device.h"
|
||||||
|
#include "world/world.h"
|
||||||
|
|
||||||
|
#include "models/entity.h"
|
||||||
|
#include "models/components.h"
|
||||||
|
|
||||||
|
uint64_t splitter_spawn(void) {
|
||||||
|
ecs_entity_t e = device_spawn(ASSET_SPLITTER);
|
||||||
|
|
||||||
|
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
|
||||||
|
*storage = (ItemContainer){0};
|
||||||
|
|
||||||
|
ecs_set(world_ecs(), e, ItemRouter, {1});
|
||||||
|
return (uint64_t)e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void splitter_despawn(uint64_t ent_id) {
|
||||||
|
entity_despawn(ent_id);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "platform/system.h"
|
||||||
|
|
||||||
|
uint64_t splitter_spawn(void);
|
||||||
|
void splitter_despawn(uint64_t id);
|
||||||
|
|
|
@ -65,6 +65,12 @@ void PushItemsOnNodes(ecs_iter_t *it) {
|
||||||
// We need a way to refer to specific blocks in the world so we can do easy block ID checks
|
// We need a way to refer to specific blocks in the world so we can do easy block ID checks
|
||||||
// and re-build the cache when a change is detected.
|
// and re-build the cache when a change is detected.
|
||||||
|
|
||||||
|
Producer *producer = ecs_get_mut_if_ex(it->world, it->entities[i], Producer);
|
||||||
|
|
||||||
|
if (producer) {
|
||||||
|
if (producer->push_filter == PRODUCER_PUSH_NONE)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
float push_dx[4], push_dy[4];
|
float push_dx[4], push_dy[4];
|
||||||
uint8_t nodes = CheckForNearbyBelts(&p[i], push_dx, push_dy);
|
uint8_t nodes = CheckForNearbyBelts(&p[i], push_dx, push_dy);
|
||||||
|
@ -82,9 +88,19 @@ void PushItemsOnNodes(ecs_iter_t *it) {
|
||||||
Item *item = item_get_data(item_slot_ent);
|
Item *item = item_get_data(item_slot_ent);
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
|
|
||||||
if (craft_is_reagent_used_in_producer(item->kind, d[i].asset)) {
|
if (producer) {
|
||||||
// NOTE(zaklaus): this is an input reagent, keep it
|
if (producer->push_filter == PRODUCER_PUSH_ANY) {
|
||||||
continue;
|
if (craft_is_reagent_used_in_producer(item->kind, d[i].asset)) {
|
||||||
|
// NOTE(zaklaus): this is an input reagent, keep it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (producer->push_filter == PRODUCER_PUSH_PRODUCT) {
|
||||||
|
if (producer->target_item != item->kind) {
|
||||||
|
// NOTE(zaklaus): this is not a producer's output, keep it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (item->quantity > 0 && num_nodes > 0) {
|
while (item->quantity > 0 && num_nodes > 0) {
|
||||||
|
|
|
@ -31,9 +31,21 @@ void ProduceItems(ecs_iter_t *it) {
|
||||||
uint64_t e = item_spawn(producer[i].processed_item, producer[i].processed_item_qty);
|
uint64_t e = item_spawn(producer[i].processed_item, producer[i].processed_item_qty);
|
||||||
entity_set_position(e, p[i].x, p[i].y);
|
entity_set_position(e, p[i].x, p[i].y);
|
||||||
producer[i].processed_item = 0;
|
producer[i].processed_item = 0;
|
||||||
|
|
||||||
|
if (producer[i].pending_task == PRODUCER_CRAFT_BUSY)
|
||||||
|
producer[i].pending_task = PRODUCER_CRAFT_WAITING;
|
||||||
} else {
|
} else {
|
||||||
producer[i].processed_item = craft_perform_recipe(storage[i].items, d[i].asset, &producer[i].processed_item_qty);
|
if (producer[i].pending_task != PRODUCER_CRAFT_WAITING) {
|
||||||
producer[i].process_time = game_time() + game_rules.furnace_cook_time;
|
producer[i].processed_item = craft_perform_recipe(storage[i].items, d[i].asset, producer[i].target_item, &producer[i].processed_item_qty);
|
||||||
|
producer[i].process_time = game_time() + game_rules.furnace_cook_time;
|
||||||
|
|
||||||
|
if (producer[i].pending_task == PRODUCER_CRAFT_ENQUEUED) {
|
||||||
|
if (producer[i].processed_item > 0)
|
||||||
|
producer[i].pending_task = PRODUCER_CRAFT_BUSY;
|
||||||
|
else
|
||||||
|
producer[i].pending_task = PRODUCER_CRAFT_WAITING;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue