ecs: rework crafting to tick-based process

efd/v1
Dominik Madarász 2023-01-14 10:24:57 +01:00
parent e15cdab4ff
commit f0ccac8e0c
19 changed files with 6252 additions and 6167 deletions

11
CMakePresets.json 100644
View File

@ -0,0 +1,11 @@
{
"version": 2,
"buildPresets": [
{
"name": "vs2022-debug",
"displayName": "Visual Studio Community 2022 Release - x86_amd64 - Debug",
"configurePreset": "vs2022",
"configuration": "Debug"
}
]
}

View File

@ -7,6 +7,7 @@ add_library(eco2d-foundation STATIC
src/platform/signal_handling.c
src/platform/profiler.c
src/platform/input.c
src/models/assets.c
src/models/components.c

View File

@ -5,7 +5,6 @@ typedef struct {
float phy_walk_drag;
uint64_t demo_npc_move_speed;
uint64_t demo_npc_steer_speed;
float furnace_cook_time;
float item_pick_radius;
float item_merger_radius;
float item_attract_radius;

View File

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

View File

@ -41,7 +41,7 @@ void buildmode_draw(void) {
buildmode_clear_buffers();
}
if (IsKeyPressed(KEY_B)){
if (input_is_pressed(IN_TOGGLE_DEMOLITION)){
build_is_deletion_mode = !build_is_deletion_mode;
}

View File

@ -251,7 +251,7 @@ void inventory_draw() {
entity_view *e = game_world_view_active_get_entity(cam.ent_id);
if (!e || !e->has_items) return;
if (IsKeyPressed(KEY_TAB)) {
if (input_is_pressed(IN_TOGGLE_INV)) {
inv_is_open = !inv_is_open;
}
@ -264,9 +264,4 @@ void inventory_draw() {
inventory_render_held_item(true);
inventory_render_held_item(false);
// TODO(zaklaus): draw craft list
if (IsKeyPressed(KEY_O)) {
player_inv.craft_item = ASSET_SCREWS;
}
}

View File

@ -6,10 +6,11 @@
.qty = qty1\
}
#define RECIPE(id,prod,qty,...)\
#define RECIPE(id,prod,qty,ticks,...)\
{\
.product = id,\
.product_qty = qty,\
.process_ticks = ticks,\
.producer = prod,\
.reagents = (reagent[]){\
__VA_ARGS__\
@ -18,9 +19,9 @@ __VA_ARGS__\
static recipe recipes[] = {
// NOTE(zaklaus): Belt
RECIPE(ASSET_IRON_PLATES, ASSET_FURNACE, 4, R(ASSET_IRON_ORE, 1), {0}),
RECIPE(ASSET_SCREWS, ASSET_CRAFTBENCH, 8, R(ASSET_IRON_PLATES, 1), {0}),
RECIPE(ASSET_BELT, ASSET_ASSEMBLER, 1, R(ASSET_FENCE, 1), R(ASSET_SCREWS, 4), R(ASSET_IRON_PLATES, 2), {0}),
RECIPE(ASSET_IRON_PLATES, ASSET_FURNACE, 4, 20, R(ASSET_IRON_ORE, 1), {0}),
RECIPE(ASSET_SCREWS, ASSET_CRAFTBENCH, 8, 40, R(ASSET_IRON_PLATES, 1), {0}),
RECIPE(ASSET_BELT, ASSET_ASSEMBLER, 1,120, R(ASSET_FENCE, 1), R(ASSET_SCREWS, 4), R(ASSET_IRON_PLATES, 2), {0}),
};
#define MAX_RECIPES (sizeof(recipes)/sizeof(recipes[0]))

View File

@ -11,7 +11,8 @@ static item_desc items[] = {
ITEM_SELF(ASSET_TEST_TALL, 64),
// ITEM_BLUEPRINT(ASSET_BLUEPRINT, 1, 4, 4, "]]]]]CF] ]]]]]"),
ITEM_BLUEPRINT_PROXY(ASSET_BLUEPRINT_DEMO_HOUSE, ASSET_BLUEPRINT, 1, 4, 4, PROT({ ASSET_WOOD,ASSET_WOOD,ASSET_WOOD,ASSET_WOOD,
ITEM_BLUEPRINT_PROXY(ASSET_BLUEPRINT_DEMO_HOUSE, ASSET_BLUEPRINT, 1, 4, 4,
PROT({ ASSET_WOOD,ASSET_WOOD,ASSET_WOOD,ASSET_WOOD,
ASSET_WOOD,ASSET_FURNACE,ASSET_CHEST,ASSET_WOOD,
ASSET_WOOD,ASSET_EMPTY,ASSET_EMPTY,ASSET_WOOD,
ASSET_WOOD,ASSET_WOOD,ASSET_EMPTY,ASSET_WOOD})),

View File

@ -147,7 +147,8 @@ typedef struct {
asset_id target_item;
asset_id processed_item;
uint32_t processed_item_qty;
float process_time;
int32_t process_ticks;
int32_t process_ticks_left;
float energy_level;
uint8_t pending_task;
uint8_t push_filter;

View File

@ -9,6 +9,7 @@ typedef struct {
typedef struct {
asset_id product;
uint32_t product_qty;
int32_t process_ticks;
asset_id producer;
reagent *reagents;
} recipe;
@ -60,7 +61,7 @@ asset_id craft_get_recipe_asset(uint16_t id) {
return recipes[id].product;
}
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id target, uint32_t *quantity) {
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id target, uint32_t *quantity, int32_t *process_ticks) {
ZPL_ASSERT_NOT_NULL(items);
for (int i = 0; i < ITEMS_CONTAINER_SIZE; i++) {
@ -146,6 +147,7 @@ asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id t
// NOTE(zaklaus): all done, return the product and its qty
*quantity = rec->product_qty;
*process_ticks = rec->process_ticks;
return rec->product;
}
}

View File

@ -7,7 +7,7 @@
// NOTE(zaklaus): resolves recipe dependencies and consumes reagents
// to enqueue a production of a new item.
// TODO(zaklaus): "items" is assumed to come from ItemContainer component.
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id target, uint32_t *quantity);
asset_id craft_perform_recipe(ecs_entity_t *items, asset_id producer, asset_id target, uint32_t *quantity, int32_t *process_ticks);
// NOTE(zaklaus): mostly used by item router so we don't push reagents out
bool craft_is_reagent_used_in_producer(asset_id reagent, asset_id producer);

View File

@ -25,8 +25,7 @@ void ProduceItems(ecs_iter_t *it) {
// TODO(zaklaus): handle fuel
// if (producer[i].energy_level <= 0.0f) continue;
// TODO(zaklaus): use ticks
if (producer[i].process_time < game_time()) {
if (producer[i].process_ticks_left == 0) {
if (producer[i].processed_item > 0) {
uint64_t e = item_spawn(producer[i].processed_item, producer[i].processed_item_qty);
entity_set_position(e, p[i].x, p[i].y);
@ -36,8 +35,8 @@ void ProduceItems(ecs_iter_t *it) {
producer[i].pending_task = PRODUCER_CRAFT_WAITING;
} else {
if (producer[i].pending_task != PRODUCER_CRAFT_WAITING) {
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;
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_ticks);
producer[i].process_ticks_left = producer[i].process_ticks;
if (producer[i].pending_task == PRODUCER_CRAFT_ENQUEUED) {
if (producer[i].processed_item > 0)
@ -51,11 +50,13 @@ void ProduceItems(ecs_iter_t *it) {
}
d[i].progress_active = (producer[i].processed_item > 0);
d[i].progress_value = 1.0f-((producer[i].process_time - game_time()) / game_rules.furnace_cook_time);
d[i].progress_value = 1.0f-(producer[i].process_ticks_left / (float)producer[i].process_ticks);
if (d[i].progress_active) {
entity_wake(it->entities[i]);
}
producer[i].process_ticks_left = zpl_max(producer[i].process_ticks_left-1, 0) ;
}
}

View File

@ -37,6 +37,7 @@ pkt_desc pkt_entity_view_desc[] = {
{ PKT_KEEP_IF(entity_view, kind, EKIND_DEVICE, 3) },
{ PKT_UINT(entity_view, asset) },
{ PKT_UINT(entity_view, progress_active) },
{ PKT_UINT(entity_view, is_producer) },
{ PKT_HALF(entity_view, progress_value) },
{ PKT_KEEP_IF(entity_view, has_items, true, 3) },
@ -47,10 +48,11 @@ pkt_desc pkt_entity_view_desc[] = {
{ PKT_UINT(entity_view, pick_ent) },
{ PKT_UINT(entity_view, sel_ent) },
{ PKT_KEEP_IF(entity_view, has_storage_items, true, 3) },
{ PKT_KEEP_IF(entity_view, has_storage_items, true, 4) },
{ PKT_UINT(entity_view, has_storage_items) },
{ PKT_UINT(entity_view, storage_selected_item) },
{ PKT_ARRAY(entity_view, storage_items) },
{ PKT_ARRAY(entity_view, craftables) },
{ PKT_END },
};

View File

@ -6,6 +6,8 @@
#define ZPL_PICO
#include "zpl.h"
#define MAX_CRAFTABLES 32
typedef enum {
EKIND_SERVER = 0,
EKIND_PLAYER,
@ -66,6 +68,7 @@ typedef struct entity_view {
float durability;
// NOTE(zaklaus): device progress bar
bool is_producer;
uint32_t progress_active;
float progress_value;
@ -79,6 +82,9 @@ typedef struct entity_view {
Item storage_items[ITEMS_CONTAINER_SIZE];
uint8_t storage_selected_item;
// NOTE(zaklaus): craftable recipes
uint8_t craftables[MAX_CRAFTABLES];
// NOTE(zaklaus): entity picking
uint64_t pick_ent;
uint64_t sel_ent;

View File

@ -71,6 +71,7 @@ entity_view *world_build_entity_view(int64_t e) {
view.asset = dev->asset;
view.progress_active = dev->progress_active;
view.progress_value = dev->progress_value;
view.is_producer = ecs_get(world_ecs(), e, Producer) != 0;
}
view.inside_vehicle = ecs_get(world_ecs(), e, IsInVehicle) != 0 ? true : false;
@ -101,6 +102,11 @@ entity_view *world_build_entity_view(int64_t e) {
}
view.storage_selected_item = in->storage_selected_item;
if (ecs_get(world_ecs(), e, Producer)) {
Device const* dev = ecs_get(world_ecs(), e, Device);
}
}
}
}

View File

@ -7,6 +7,7 @@
#include "world/prediction.h"
#include "core/camera.h"
#include "math.h"
#include "platform/input.h"
#include "world/blocks.h"
#include "models/assets.h"
#include "platform/profiler.h"
@ -61,15 +62,15 @@ void platform_input() {
{
float x=0.0f, y=0.0f;
uint8_t use, sprint, drop, ctrl, pick;
if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) x += 1.0f;
if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) x -= 1.0f;
if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) y += 1.0f;
if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) y -= 1.0f;
if (input_is_down(IN_RIGHT)) x += 1.0f;
if (input_is_down(IN_LEFT)) x -= 1.0f;
if (input_is_down(IN_UP)) y += 1.0f;
if (input_is_down(IN_DOWN)) y -= 1.0f;
use = IsKeyPressed(KEY_SPACE);
sprint = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT);
ctrl = IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL);
drop = IsKeyPressed(KEY_G) || player_inv.drop_item || storage_inv.drop_item;
use = input_is_pressed(IN_USE);
sprint = input_is_down(IN_SPRINT);
ctrl = input_is_down(IN_CTRL);
drop = input_is_pressed(IN_DROP) || player_inv.drop_item || storage_inv.drop_item;
// NOTE(zaklaus): NEW! mouse movement
Vector2 mouse_pos = GetMousePosition();

59
eco2d.10x 100644
View File

@ -0,0 +1,59 @@
<?xml version="1.0"?>
<N10X>
<Workspace>
<IncludeFilter>*.*,</IncludeFilter>
<ExcludeFilter>*.obj,*.lib,*.pch,*.dll,*.pdb,.vs,Debug,Release,x64,obj,*.user,Intermediate,</ExcludeFilter>
<SyncFiles>true</SyncFiles>
<Recursive>true</Recursive>
<IsVirtual>false</IsVirtual>
<IsFolder>false</IsFolder>
<BuildCommand>build.bat</BuildCommand>
<RebuildCommand></RebuildCommand>
<BuildFileCommand></BuildFileCommand>
<CleanCommand></CleanCommand>
<BuildWorkingDirectory></BuildWorkingDirectory>
<RunCommand></RunCommand>
<DebugCommand></DebugCommand>
<ExePathCommand></ExePathCommand>
<DebugSln></DebugSln>
<UseVisualStudioEnvBat>false</UseVisualStudioEnvBat>
<Configurations>
<Configuration>Debug</Configuration>
<Configuration>Release</Configuration>
</Configurations>
<Platforms>
<Platform>x64</Platform>
</Platforms>
<AdditionalIncludePaths>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt</AdditionalIncludePath>
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
</AdditionalIncludePaths>
<Defines>
<Define>ZPL_IMPL</Define>
<Define>_WIN32</Define>
<Define>_WIN64</Define>
</Defines>
<ConfigProperties>
<ConfigAndPlatform>
<Name>Debug:x64</Name>
<Defines></Defines>
<ForceIncludes></ForceIncludes>
</ConfigAndPlatform>
<Config>
<Name>Debug</Name>
<Defines></Defines>
</Config>
<Platform>
<Name>x64</Name>
<Defines></Defines>
</Platform>
</ConfigProperties>
<Children></Children>
</Workspace>
</N10X>