inventory system
parent
a8f357184f
commit
36232e1e20
|
@ -147,6 +147,7 @@ void debug_replay_run(void) {
|
||||||
*pos = *p1;
|
*pos = *p1;
|
||||||
|
|
||||||
ecs_set(world_ecs(), mime, Input, {0});
|
ecs_set(world_ecs(), mime, Input, {0});
|
||||||
|
ecs_set(world_ecs(), mime, Inventory, {0});
|
||||||
|
|
||||||
camera_set_follow(mime);
|
camera_set_follow(mime);
|
||||||
}
|
}
|
||||||
|
@ -167,8 +168,16 @@ void debug_replay_update(void) {
|
||||||
Input *i = ecs_get_mut(world_ecs(), mime, Input, NULL);
|
Input *i = ecs_get_mut(world_ecs(), mime, Input, NULL);
|
||||||
i->x = r->pkt.x;
|
i->x = r->pkt.x;
|
||||||
i->y = r->pkt.y;
|
i->y = r->pkt.y;
|
||||||
|
i->mx = r->pkt.mx;
|
||||||
|
i->my = r->pkt.my;
|
||||||
i->use = r->pkt.use;
|
i->use = r->pkt.use;
|
||||||
i->sprint = r->pkt.sprint;
|
i->sprint = r->pkt.sprint;
|
||||||
|
i->ctrl = r->pkt.ctrl;
|
||||||
|
i->selected_item = r->pkt.selected_item;
|
||||||
|
i->drop = r->pkt.drop;
|
||||||
|
i->swap = r->pkt.swap;
|
||||||
|
i->swap_from = r->pkt.swap_from;
|
||||||
|
i->swap_to = r->pkt.swap_to;
|
||||||
}break;
|
}break;
|
||||||
case RPKIND_SPAWN_CAR: {
|
case RPKIND_SPAWN_CAR: {
|
||||||
ecs_entity_t e = vehicle_spawn();
|
ecs_entity_t e = vehicle_spawn();
|
||||||
|
|
|
@ -72,18 +72,6 @@ typedef struct debug_item {
|
||||||
debug_draw_result (*proc)(struct debug_item*, float, float);
|
debug_draw_result (*proc)(struct debug_item*, float, float);
|
||||||
} debug_item;
|
} debug_item;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
DAREA_OUTSIDE,
|
|
||||||
DAREA_HOVER,
|
|
||||||
DAREA_HELD,
|
|
||||||
DAREA_PRESS,
|
|
||||||
|
|
||||||
DAREA_FORCE_UINT8 = UINT8_MAX
|
|
||||||
} debug_area_status;
|
|
||||||
|
|
||||||
debug_area_status check_mouse_area(float xpos, float ypos, float w, float h);
|
|
||||||
bool is_btn_pressed(float xpos, float ypos, float w, float h, Color *color);
|
|
||||||
|
|
||||||
static void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color);
|
static void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color);
|
||||||
static int UIMeasureText(const char *text, int fontSize);
|
static int UIMeasureText(const char *text, int fontSize);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
void debug_draw(void);
|
void debug_draw(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DAREA_OUTSIDE,
|
||||||
|
DAREA_HOVER,
|
||||||
|
DAREA_HELD,
|
||||||
|
DAREA_PRESS,
|
||||||
|
|
||||||
|
DAREA_FORCE_UINT8 = UINT8_MAX
|
||||||
|
} debug_area_status;
|
||||||
|
|
||||||
|
debug_area_status check_mouse_area(float xpos, float ypos, float w, float h);
|
||||||
|
bool is_btn_pressed(float xpos, float ypos, float w, float h, Color *color);
|
||||||
|
|
|
@ -63,7 +63,7 @@ ActPlaceIceRink(void) {
|
||||||
for (int y = 0; y < 100; y++) {
|
for (int y = 0; y < 100; y++) {
|
||||||
for (int x = 0; x < 100; x++) {
|
for (int x = 0; x < 100; x++) {
|
||||||
world_block_lookup l = world_block_from_realpos((p->x - (x*bs)/2.0f), p->y - (y*bs)/2.0f);
|
world_block_lookup l = world_block_from_realpos((p->x - (x*bs)/2.0f), p->y - (y*bs)/2.0f);
|
||||||
world_chunk_replace_outer_block(world_ecs(), l.chunk_id, l.id, watr_id);
|
world_chunk_replace_outer_block(l.chunk_id, l.id, watr_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ ActEraseWorldChanges(void) {
|
||||||
for (int y = 0; y < 100; y++) {
|
for (int y = 0; y < 100; y++) {
|
||||||
for (int x = 0; x < 100; x++) {
|
for (int x = 0; x < 100; x++) {
|
||||||
world_block_lookup l = world_block_from_realpos((p->x - (x*bs)/2.0f), p->y - (y*bs)/2.0f);
|
world_block_lookup l = world_block_from_realpos((p->x - (x*bs)/2.0f), p->y - (y*bs)/2.0f);
|
||||||
world_chunk_replace_outer_block(world_ecs(), l.chunk_id, l.id, 0);
|
world_chunk_replace_outer_block(l.chunk_id, l.id, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,14 @@ pkt_desc pkt_entity_view_desc[] = {
|
||||||
{ PKT_KEEP_IF(entity_view, kind, EKIND_VEHICLE, 1) }, // NOTE(zaklaus): keep for vehicles
|
{ PKT_KEEP_IF(entity_view, kind, EKIND_VEHICLE, 1) }, // NOTE(zaklaus): keep for vehicles
|
||||||
{ PKT_HALF(entity_view, heading) },
|
{ PKT_HALF(entity_view, heading) },
|
||||||
|
|
||||||
{ PKT_KEEP_IF(entity_view, kind, EKIND_ITEM, 1) },
|
{ PKT_KEEP_IF(entity_view, kind, EKIND_ITEM, 2) },
|
||||||
{ PKT_UINT(entity_view, asset) },
|
{ PKT_UINT(entity_view, asset) },
|
||||||
|
{ PKT_UINT(entity_view, quantity) },
|
||||||
|
|
||||||
|
{ PKT_KEEP_IF(entity_view, has_items, true, 3) },
|
||||||
|
{ PKT_UINT(entity_view, has_items) },
|
||||||
|
{ PKT_ARRAY(entity_view, items) },
|
||||||
|
{ PKT_UINT(entity_view, selected_item) },
|
||||||
|
|
||||||
{ PKT_END },
|
{ PKT_END },
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "assets.h"
|
#include "assets.h"
|
||||||
|
#include "items.h"
|
||||||
|
|
||||||
|
#include "modules/components.h"
|
||||||
|
|
||||||
#define ZPL_PICO
|
#define ZPL_PICO
|
||||||
#include "zpl.h"
|
#include "zpl.h"
|
||||||
|
@ -57,6 +60,12 @@ typedef struct entity_view {
|
||||||
|
|
||||||
// NOTE(zaklaus): items, ...
|
// NOTE(zaklaus): items, ...
|
||||||
asset_id asset;
|
asset_id asset;
|
||||||
|
uint32_t quantity;
|
||||||
|
|
||||||
|
// NOTE(zaklaus): inventory
|
||||||
|
uint8_t has_items;
|
||||||
|
ItemDrop items[ITEMS_INVENTORY_SIZE];
|
||||||
|
uint8_t selected_item;
|
||||||
|
|
||||||
// NOTE(zaklaus): internals
|
// NOTE(zaklaus): internals
|
||||||
uint8_t layer_id;
|
uint8_t layer_id;
|
||||||
|
|
|
@ -92,6 +92,10 @@ void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_vie
|
||||||
entity_view_map(&active_viewer->entities, map_proc);
|
entity_view_map(&active_viewer->entities, map_proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_view *game_world_view_active_get_entity(uint64_t ent_id) {
|
||||||
|
return entity_view_get(&active_viewer->entities, ent_id);
|
||||||
|
}
|
||||||
|
|
||||||
void game_world_view_set_active(world_view *view) {
|
void game_world_view_set_active(world_view *view) {
|
||||||
active_viewer = view;
|
active_viewer = view;
|
||||||
camera_set_follow(view->owner_id);
|
camera_set_follow(view->owner_id);
|
||||||
|
@ -170,8 +174,19 @@ void game_render() {
|
||||||
platform_render();
|
platform_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_action_send_keystate(float x, float y, uint8_t use, uint8_t sprint) {
|
void game_action_send_keystate(float x,
|
||||||
pkt_send_keystate_send(active_viewer->view_id, x, y, use, sprint);
|
float y,
|
||||||
|
float mx,
|
||||||
|
float my,
|
||||||
|
uint8_t use,
|
||||||
|
uint8_t sprint,
|
||||||
|
uint8_t ctrl,
|
||||||
|
uint8_t drop,
|
||||||
|
uint8_t selected_item,
|
||||||
|
uint8_t swap,
|
||||||
|
uint8_t swap_from,
|
||||||
|
uint8_t swap_to) {
|
||||||
|
pkt_send_keystate_send(active_viewer->view_id, x, y, mx, my, use, sprint, ctrl, drop, selected_item, swap, swap_from, swap_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GAME_ENT_REMOVAL_TIME 10000
|
#define GAME_ENT_REMOVAL_TIME 10000
|
||||||
|
|
|
@ -28,7 +28,19 @@ void game_world_view_set_active_by_idx(uint16_t idx);
|
||||||
void game_world_view_set_active(world_view *view);
|
void game_world_view_set_active(world_view *view);
|
||||||
void game_world_view_cycle_active(int8_t dir);
|
void game_world_view_cycle_active(int8_t dir);
|
||||||
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view * value));
|
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view * value));
|
||||||
|
entity_view *game_world_view_active_get_entity(uint64_t ent_id);
|
||||||
void game_world_cleanup_entities(void);
|
void game_world_cleanup_entities(void);
|
||||||
|
|
||||||
//~ NOTE(zaklaus): viewer -> host actions
|
//~ NOTE(zaklaus): viewer -> host actions
|
||||||
void game_action_send_keystate(float x, float y, uint8_t use, uint8_t sprint);
|
void game_action_send_keystate(float x,
|
||||||
|
float y,
|
||||||
|
float mx,
|
||||||
|
float my,
|
||||||
|
uint8_t use,
|
||||||
|
uint8_t sprint,
|
||||||
|
uint8_t ctrl,
|
||||||
|
uint8_t drop,
|
||||||
|
uint8_t selected_item,
|
||||||
|
uint8_t swap,
|
||||||
|
uint8_t swap_from,
|
||||||
|
uint8_t swap_to);
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include "items.h"
|
||||||
|
|
||||||
|
static uint8_t inv_selected_item = 0;
|
||||||
|
static bool inv_drop_item = false;
|
||||||
|
static bool inv_is_open = false;
|
||||||
|
|
||||||
|
static bool inv_item_is_held = false;
|
||||||
|
static uint8_t inv_held_item_idx = 0;
|
||||||
|
static ItemDrop inv_held_item = {0};
|
||||||
|
|
||||||
|
static bool inv_swap = false;
|
||||||
|
static uint8_t inv_swap_from = 0;
|
||||||
|
static uint8_t inv_swap_to = 0;
|
||||||
|
|
||||||
|
void inventory_draw() {
|
||||||
|
inv_drop_item = false;
|
||||||
|
inv_swap = false;
|
||||||
|
|
||||||
|
camera cam = camera_get();
|
||||||
|
entity_view *e = game_world_view_active_get_entity(cam.ent_id);
|
||||||
|
if (!e || !e->has_items) return;
|
||||||
|
|
||||||
|
if (IsKeyPressed(KEY_TAB)) {
|
||||||
|
inv_is_open = !inv_is_open;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inv_is_open) return;
|
||||||
|
|
||||||
|
float sx = screenWidth/2.0f + 128;
|
||||||
|
float sy = screenHeight/2.0f - 96;
|
||||||
|
|
||||||
|
float x = sx;
|
||||||
|
float y = sy;
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < ITEMS_INVENTORY_SIZE; i += 1) {
|
||||||
|
{
|
||||||
|
debug_area_status area = check_mouse_area(x, y, 64, 64);
|
||||||
|
Color color = RAYWHITE;
|
||||||
|
ItemDrop *item = &e->items[i];
|
||||||
|
|
||||||
|
if (area == DAREA_HOVER) {
|
||||||
|
color = YELLOW;
|
||||||
|
} else if (area == DAREA_PRESS && !inv_item_is_held) {
|
||||||
|
color = VIOLET;
|
||||||
|
inv_selected_item = i;
|
||||||
|
} else if (area == DAREA_PRESS && inv_item_is_held) {
|
||||||
|
color = VIOLET;
|
||||||
|
inv_selected_item = i;
|
||||||
|
inv_item_is_held = false;
|
||||||
|
inv_swap = true;
|
||||||
|
inv_swap_from = inv_held_item_idx;
|
||||||
|
inv_swap_to = i;
|
||||||
|
} else if (area == DAREA_HELD && item->quantity > 0 && !inv_item_is_held) {
|
||||||
|
inv_selected_item = i;
|
||||||
|
inv_held_item = *item;
|
||||||
|
inv_item_is_held = true;
|
||||||
|
inv_held_item_idx = i;
|
||||||
|
} else if (i == inv_selected_item) {
|
||||||
|
color = RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawRectangleLinesEco(x, y, 64, 64, color);
|
||||||
|
|
||||||
|
if (item->quantity > 0) {
|
||||||
|
asset_id asset = item_get_asset(item->kind);
|
||||||
|
DrawTexturePro(GetSpriteTexture2D(assets_find(asset)), ASSET_SRC_RECT(), ASSET_DST_RECT(x,y), (Vector2){0.5f,0.5f}, 0.0f, WHITE);
|
||||||
|
DrawTextEco(zpl_bprintf("%d", item->quantity), x+5, y+5, 16, RAYWHITE, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x += 64;
|
||||||
|
|
||||||
|
if ((i+1) % 3 == 0) {
|
||||||
|
x = sx;
|
||||||
|
y += 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inv_item_is_held) {
|
||||||
|
Vector2 mpos = GetMousePosition();
|
||||||
|
mpos.x -= 32;
|
||||||
|
mpos.y -= 32;
|
||||||
|
asset_id asset = item_get_asset(item_find(inv_held_item.kind));
|
||||||
|
DrawTexturePro(GetSpriteTexture2D(assets_find(asset)), ASSET_SRC_RECT(), ASSET_DST_RECT(mpos.x, mpos.y), (Vector2){0.5f,0.5f}, 0.0f, ColorAlpha(WHITE, 0.8f));
|
||||||
|
DrawTextEco(zpl_bprintf("%d", inv_held_item.quantity), mpos.x, mpos.y, 16, RAYWHITE, 0.0f);
|
||||||
|
|
||||||
|
debug_area_status area = check_mouse_area(sx, sy, 64*3, 64*3);
|
||||||
|
if (area == DAREA_OUTSIDE && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
|
||||||
|
inv_drop_item = true;
|
||||||
|
inv_item_is_held = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,15 @@
|
||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
#include "entity_view.h"
|
#include "entity_view.h"
|
||||||
#include "world/world.h"
|
#include "world/world.h"
|
||||||
|
#include "world/blocks.h"
|
||||||
|
|
||||||
#include "modules/components.h"
|
#include "modules/components.h"
|
||||||
|
|
||||||
|
#include "zpl.h"
|
||||||
|
|
||||||
|
#include "items_list.c"
|
||||||
|
#define ITEMS_COUNT (sizeof(items)/sizeof(item_desc))
|
||||||
|
|
||||||
uint64_t item_spawn(item_kind kind, uint32_t qty) {
|
uint64_t item_spawn(item_kind kind, uint32_t qty) {
|
||||||
ecs_entity_t e = entity_spawn(EKIND_ITEM);
|
ecs_entity_t e = entity_spawn(EKIND_ITEM);
|
||||||
|
|
||||||
|
@ -17,15 +23,42 @@ uint64_t item_spawn(item_kind kind, uint32_t qty) {
|
||||||
return (uint64_t)e;
|
return (uint64_t)e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t item_find(item_kind kind) {
|
||||||
|
for (uint32_t i=0; i<ITEMS_COUNT; i++) {
|
||||||
|
if (items[i].kind == kind)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return ITEMS_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void item_use(ecs_world_t *ecs, ItemDrop *it, Position p) {
|
||||||
|
(void)ecs;
|
||||||
|
uint16_t item_id = item_find(it->kind);
|
||||||
|
item_desc *desc = &items[item_id];
|
||||||
|
switch (item_get_usage(item_id)) {
|
||||||
|
case UKIND_PLACE:{
|
||||||
|
world_block_lookup l = world_block_from_realpos(p.x, p.y);
|
||||||
|
world_chunk_replace_outer_block(l.chunk_id, l.id, blocks_find(desc->place.biome, desc->place.kind));
|
||||||
|
it->quantity--;
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void item_despawn(uint64_t id) {
|
void item_despawn(uint64_t id) {
|
||||||
entity_despawn(id);
|
entity_despawn(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
asset_id item_get_asset(item_kind kind) {
|
uint32_t item_max_quantity(uint16_t id) {
|
||||||
switch (kind) {
|
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
|
||||||
case IKIND_DEMO_ICEMAKER: return ASSET_DEMO_ICEMAKER;
|
return items[id].max_quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZPL_PANIC("unreachable code");
|
asset_id item_get_asset(uint16_t id) {
|
||||||
return 0;
|
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
|
||||||
|
return items[id].asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_usage item_get_usage(uint16_t id) {
|
||||||
|
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
|
||||||
|
return items[id].usage;
|
||||||
}
|
}
|
|
@ -1,14 +1,46 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "assets.h"
|
#include "assets.h"
|
||||||
|
#include "world/blocks.h"
|
||||||
|
|
||||||
|
#include "modules/components.h"
|
||||||
|
|
||||||
|
#define ITEMS_INVALID 0xFF
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
IKIND_DEMO_ICEMAKER,
|
IKIND_DEMO_ICEMAKER,
|
||||||
} item_kind;
|
} item_kind;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UKIND_PLACE,
|
||||||
|
} item_usage;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
item_kind kind;
|
||||||
|
item_usage usage;
|
||||||
|
asset_id asset;
|
||||||
|
uint32_t max_quantity;
|
||||||
|
|
||||||
|
// NOTE(zaklaus): usage data
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
block_biome biome;
|
||||||
|
block_kind kind;
|
||||||
|
} place;
|
||||||
|
};
|
||||||
|
} item_desc;
|
||||||
|
|
||||||
|
// NOTE(zaklaus): item drops
|
||||||
uint64_t item_spawn(item_kind kind, uint32_t qty);
|
uint64_t item_spawn(item_kind kind, uint32_t qty);
|
||||||
void item_despawn(uint64_t id);
|
void item_despawn(uint64_t id);
|
||||||
|
|
||||||
|
// NOTE(zaklaus): items
|
||||||
|
uint16_t item_find(item_kind kind);
|
||||||
|
void item_use(ecs_world_t *ecs, ItemDrop *it, Position p);
|
||||||
|
|
||||||
|
uint32_t item_max_quantity(uint16_t id);
|
||||||
|
item_usage item_get_usage(uint16_t id);
|
||||||
|
|
||||||
// NOTE(zaklaus): client
|
// NOTE(zaklaus): client
|
||||||
|
|
||||||
asset_id item_get_asset(item_kind kind);
|
asset_id item_get_asset(uint16_t id);
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "items.h"
|
||||||
|
|
||||||
|
static item_desc items[] = {
|
||||||
|
{
|
||||||
|
.kind = IKIND_DEMO_ICEMAKER,
|
||||||
|
.usage = UKIND_PLACE,
|
||||||
|
.asset = ASSET_DEMO_ICEMAKER,
|
||||||
|
.max_quantity = 4,
|
||||||
|
|
||||||
|
.place = {
|
||||||
|
.biome = BLOCK_BIOME_DEV,
|
||||||
|
.kind = BLOCK_KIND_WATER,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -9,17 +9,33 @@
|
||||||
pkt_desc pkt_send_keystate_desc[] = {
|
pkt_desc pkt_send_keystate_desc[] = {
|
||||||
{ PKT_REAL(pkt_send_keystate, x) },
|
{ PKT_REAL(pkt_send_keystate, x) },
|
||||||
{ PKT_REAL(pkt_send_keystate, y) },
|
{ PKT_REAL(pkt_send_keystate, y) },
|
||||||
|
{ PKT_REAL(pkt_send_keystate, mx) },
|
||||||
|
{ PKT_REAL(pkt_send_keystate, my) },
|
||||||
{ PKT_UINT(pkt_send_keystate, use) },
|
{ PKT_UINT(pkt_send_keystate, use) },
|
||||||
{ PKT_UINT(pkt_send_keystate, sprint) },
|
{ PKT_UINT(pkt_send_keystate, sprint) },
|
||||||
|
{ PKT_UINT(pkt_send_keystate, ctrl) },
|
||||||
|
{ PKT_UINT(pkt_send_keystate, selected_item) },
|
||||||
|
{ PKT_UINT(pkt_send_keystate, drop) },
|
||||||
|
{ PKT_UINT(pkt_send_keystate, swap) },
|
||||||
|
{ PKT_UINT(pkt_send_keystate, swap_from) },
|
||||||
|
{ PKT_UINT(pkt_send_keystate, swap_to) },
|
||||||
{ PKT_END },
|
{ PKT_END },
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t pkt_send_keystate_send(uint16_t view_id,
|
size_t pkt_send_keystate_send(uint16_t view_id,
|
||||||
float x,
|
float x,
|
||||||
float y,
|
float y,
|
||||||
|
float mx,
|
||||||
|
float my,
|
||||||
uint8_t use,
|
uint8_t use,
|
||||||
uint8_t sprint) {
|
uint8_t sprint,
|
||||||
pkt_send_keystate table = { .x = x, .y = y, .use = use, .sprint = sprint };
|
uint8_t ctrl,
|
||||||
|
uint8_t drop,
|
||||||
|
uint8_t selected_item,
|
||||||
|
uint8_t swap,
|
||||||
|
uint8_t swap_from,
|
||||||
|
uint8_t swap_to) {
|
||||||
|
pkt_send_keystate table = { .x = x, .y = y, .mx = mx, .my = my, .use = use, .sprint = sprint, .ctrl = ctrl, .drop = drop, .selected_item = selected_item, .swap = swap, .swap_from = swap_from, .swap_to = swap_to };
|
||||||
return pkt_world_write(MSG_ID_SEND_KEYSTATE, pkt_send_keystate_encode(&table), 1, view_id, NULL);
|
return pkt_world_write(MSG_ID_SEND_KEYSTATE, pkt_send_keystate_encode(&table), 1, view_id, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +55,16 @@ int32_t pkt_send_keystate_handler(pkt_header *header) {
|
||||||
if (i && !i->is_blocked) {
|
if (i && !i->is_blocked) {
|
||||||
i->x = table.x;
|
i->x = table.x;
|
||||||
i->y = table.y;
|
i->y = table.y;
|
||||||
|
i->mx = table.mx;
|
||||||
|
i->my = table.my;
|
||||||
i->use = table.use;
|
i->use = table.use;
|
||||||
i->sprint = table.sprint;
|
i->sprint = table.sprint;
|
||||||
|
i->ctrl = table.ctrl;
|
||||||
|
i->selected_item = zpl_clamp(table.selected_item, 0, ITEMS_INVENTORY_SIZE-1);
|
||||||
|
i->drop = table.drop;
|
||||||
|
i->swap = table.swap;
|
||||||
|
i->swap_from = zpl_clamp(table.swap_from, 0, ITEMS_INVENTORY_SIZE-1);
|
||||||
|
i->swap_to = zpl_clamp(table.swap_to, 0, ITEMS_INVENTORY_SIZE-1);
|
||||||
debug_replay_record_keystate(table);
|
debug_replay_record_keystate(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,30 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
|
float mx;
|
||||||
|
float my;
|
||||||
uint8_t use;
|
uint8_t use;
|
||||||
uint8_t sprint;
|
uint8_t sprint;
|
||||||
|
uint8_t ctrl;
|
||||||
|
uint8_t selected_item;
|
||||||
|
uint8_t drop;
|
||||||
|
uint8_t swap;
|
||||||
|
uint8_t swap_from;
|
||||||
|
uint8_t swap_to;
|
||||||
} pkt_send_keystate;
|
} pkt_send_keystate;
|
||||||
size_t pkt_send_keystate_send(uint16_t view_id,
|
size_t pkt_send_keystate_send(uint16_t view_id,
|
||||||
float x,
|
float x,
|
||||||
float y,
|
float y,
|
||||||
|
float mx,
|
||||||
|
float my,
|
||||||
uint8_t use,
|
uint8_t use,
|
||||||
uint8_t sprint);
|
uint8_t sprint,
|
||||||
|
uint8_t ctrl,
|
||||||
|
uint8_t drop,
|
||||||
|
uint8_t selected_item,
|
||||||
|
uint8_t swap,
|
||||||
|
uint8_t swap_from,
|
||||||
|
uint8_t swap_to);
|
||||||
size_t pkt_send_keystate_encode(pkt_send_keystate *table);
|
size_t pkt_send_keystate_encode(pkt_send_keystate *table);
|
||||||
extern pkt_desc pkt_send_keystate_desc[];
|
extern pkt_desc pkt_send_keystate_desc[];
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@ static bool request_shutdown;
|
||||||
#define GFX_KIND 2
|
#define GFX_KIND 2
|
||||||
#include "renderer_bridge.c"
|
#include "renderer_bridge.c"
|
||||||
|
|
||||||
|
// NOTE(zaklaus): add-ins
|
||||||
|
#include "gui/inventory.c"
|
||||||
|
|
||||||
void platform_init() {
|
void platform_init() {
|
||||||
InitWindow(screenWidth, screenHeight, "eco2d");
|
InitWindow(screenWidth, screenHeight, "eco2d");
|
||||||
SetWindowState(FLAG_WINDOW_UNDECORATED|FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE|FLAG_MSAA_4X_HINT);
|
SetWindowState(FLAG_WINDOW_UNDECORATED|FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE|FLAG_MSAA_4X_HINT);
|
||||||
|
@ -63,7 +66,7 @@ void platform_input() {
|
||||||
// NOTE(zaklaus): keystate handling
|
// NOTE(zaklaus): keystate handling
|
||||||
{
|
{
|
||||||
float x=0.0f, y=0.0f;
|
float x=0.0f, y=0.0f;
|
||||||
uint8_t use, sprint;
|
uint8_t use, sprint, drop, ctrl;
|
||||||
if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) x += 1.0f;
|
if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) x += 1.0f;
|
||||||
if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) 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_UP) || IsKeyDown(KEY_W)) y += 1.0f;
|
||||||
|
@ -71,20 +74,23 @@ void platform_input() {
|
||||||
|
|
||||||
use = IsKeyPressed(KEY_SPACE);
|
use = IsKeyPressed(KEY_SPACE);
|
||||||
sprint = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT);
|
sprint = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT);
|
||||||
|
ctrl = IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL);
|
||||||
|
drop = IsKeyPressed(KEY_G) || inv_drop_item;
|
||||||
|
|
||||||
// NOTE(zaklaus): NEW! mouse movement
|
// NOTE(zaklaus): NEW! mouse movement
|
||||||
|
Vector2 mouse_pos = GetMousePosition();
|
||||||
|
mouse_pos.x /= screenWidth;
|
||||||
|
mouse_pos.y /= screenHeight;
|
||||||
|
mouse_pos.x -= 0.5f;
|
||||||
|
mouse_pos.y -= 0.5f;
|
||||||
|
mouse_pos = Vector2Normalize(mouse_pos);
|
||||||
|
|
||||||
if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) {
|
if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) {
|
||||||
Vector2 mouse_pos = GetMousePosition();
|
|
||||||
mouse_pos.x /= screenWidth;
|
|
||||||
mouse_pos.y /= screenHeight;
|
|
||||||
mouse_pos.x -= 0.5f;
|
|
||||||
mouse_pos.y -= 0.5f;
|
|
||||||
mouse_pos = Vector2Normalize(mouse_pos);
|
|
||||||
x = mouse_pos.x;
|
x = mouse_pos.x;
|
||||||
y = -mouse_pos.y;
|
y = -mouse_pos.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
game_action_send_keystate(x, y, use, sprint);
|
game_action_send_keystate(x, y, mouse_pos.x, mouse_pos.y, use, sprint, ctrl, drop, inv_selected_item, inv_swap, inv_swap_from, inv_swap_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(zaklaus): cycle through viewers
|
// NOTE(zaklaus): cycle through viewers
|
||||||
|
@ -126,6 +132,10 @@ void platform_render() {
|
||||||
renderer_draw();
|
renderer_draw();
|
||||||
}
|
}
|
||||||
renderer_debug_draw();
|
renderer_debug_draw();
|
||||||
|
{
|
||||||
|
// NOTE(zaklaus): add-ins
|
||||||
|
inventory_draw();
|
||||||
|
}
|
||||||
debug_draw();
|
debug_draw();
|
||||||
display_conn_status();
|
display_conn_status();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ uint64_t player_spawn(char *name) {
|
||||||
ecs_set_name(world_ecs(), e, name);
|
ecs_set_name(world_ecs(), e, name);
|
||||||
ecs_set(world_ecs(), e, ClientInfo, {0});
|
ecs_set(world_ecs(), e, ClientInfo, {0});
|
||||||
ecs_set(world_ecs(), e, Input, {0});
|
ecs_set(world_ecs(), e, Input, {0});
|
||||||
|
ecs_set(world_ecs(), e, Inventory, {0});
|
||||||
ecs_set(world_ecs(), e, Health, {.hp = PLAYER_MAX_HP, .max_hp = PLAYER_MAX_HP});
|
ecs_set(world_ecs(), e, Health, {.hp = PLAYER_MAX_HP, .max_hp = PLAYER_MAX_HP});
|
||||||
ecs_add(world_ecs(), e, Player);
|
ecs_add(world_ecs(), e, Player);
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,16 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) {
|
||||||
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-fixed_title_offset, title_w*health+title_bg_offset, font_size*0.2f, ColorAlpha(RED, data->tran_time));
|
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-fixed_title_offset, title_w*health+title_bg_offset, font_size*0.2f, ColorAlpha(RED, data->tran_time));
|
||||||
DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(RAYWHITE, data->tran_time), font_spacing);
|
DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(RAYWHITE, data->tran_time), font_spacing);
|
||||||
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
||||||
|
|
||||||
|
if (data->has_items) {
|
||||||
|
float ix = data->x;
|
||||||
|
float iy = data->y;
|
||||||
|
if (data->items[data->selected_item].quantity > 0) {
|
||||||
|
item_kind it_kind = data->items[data->selected_item].kind;
|
||||||
|
uint16_t it_id = item_find(it_kind);
|
||||||
|
DrawTexturePro(GetSpriteTexture2D(assets_find(item_get_asset(it_id))), ASSET_SRC_RECT(), ((Rectangle){ix, iy, 32, 32}), (Vector2){0.5f,0.5f}, 0.0f, ALPHA(WHITE));
|
||||||
|
}
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
case EKIND_MACRO_BOT: {
|
case EKIND_MACRO_BOT: {
|
||||||
float x = data->x;
|
float x = data->x;
|
||||||
|
@ -70,6 +80,7 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) {
|
||||||
float x = data->x - 32.f;
|
float x = data->x - 32.f;
|
||||||
float y = data->y - 32.f;
|
float y = data->y - 32.f;
|
||||||
DrawTexturePro(GetSpriteTexture2D(assets_find(data->asset)), ASSET_SRC_RECT(), ASSET_DST_RECT(x,y), (Vector2){0.5f,0.5f}, 0.0f, ALPHA(WHITE));
|
DrawTexturePro(GetSpriteTexture2D(assets_find(data->asset)), ASSET_SRC_RECT(), ASSET_DST_RECT(x,y), (Vector2){0.5f,0.5f}, 0.0f, ALPHA(WHITE));
|
||||||
|
DrawTextEco(zpl_bprintf("%d", data->quantity), x, y, 10, ALPHA(RAYWHITE), 0.0f);
|
||||||
}break;
|
}break;
|
||||||
default:break;
|
default:break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,21 @@ entity_view world_build_entity_view(int64_t e) {
|
||||||
if (ecs_get(world_ecs(), e, ItemDrop)) {
|
if (ecs_get(world_ecs(), e, ItemDrop)) {
|
||||||
ItemDrop const* dr = ecs_get(world_ecs(), e, ItemDrop);
|
ItemDrop const* dr = ecs_get(world_ecs(), e, ItemDrop);
|
||||||
view.asset = item_get_asset(dr->kind);
|
view.asset = item_get_asset(dr->kind);
|
||||||
|
view.quantity = dr->quantity;
|
||||||
|
|
||||||
|
const Input *in = ecs_get(world_ecs(), e, Input);
|
||||||
|
if (in)
|
||||||
|
view.selected_item = in->selected_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
Inventory *inv = 0;
|
||||||
|
if ((inv = ecs_get_mut_if(world_ecs(), e, Inventory))) {
|
||||||
|
view.has_items = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < ITEMS_INVENTORY_SIZE; i += 1) {
|
||||||
|
view.items[i] = inv->items[i];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk *chpos = 0;
|
Chunk *chpos = 0;
|
||||||
|
@ -305,9 +320,16 @@ uint32_t world_buf(uint8_t const **ptr, uint32_t *width) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ecs_world_t * world_ecs() {
|
ecs_world_t * world_ecs() {
|
||||||
|
if (world.ecs_stage != NULL) {
|
||||||
|
return world.ecs_stage;
|
||||||
|
}
|
||||||
return world.ecs;
|
return world.ecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void world_set_stage(ecs_world_t *ecs) {
|
||||||
|
world.ecs_stage = ecs;
|
||||||
|
}
|
||||||
|
|
||||||
librg_world *world_tracker() {
|
librg_world *world_tracker() {
|
||||||
return world.tracker;
|
return world.tracker;
|
||||||
}
|
}
|
||||||
|
@ -391,32 +413,32 @@ int64_t world_chunk_from_entity(ecs_entity_t id) {
|
||||||
return librg_entity_chunk_get(world.tracker, id);
|
return librg_entity_chunk_get(world.tracker, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void world_chunk_replace_block(ecs_world_t *ecs, int64_t id, uint16_t block_idx, uint8_t block_id) {
|
void world_chunk_replace_block(int64_t id, uint16_t block_idx, uint8_t block_id) {
|
||||||
ZPL_ASSERT(block_idx >= 0 && block_idx < zpl_square(world.chunk_size));
|
ZPL_ASSERT(block_idx >= 0 && block_idx < zpl_square(world.chunk_size));
|
||||||
world.block_mapping[id][block_idx] = block_id;
|
world.block_mapping[id][block_idx] = block_id;
|
||||||
world_chunk_mark_dirty(ecs, world.chunk_mapping[id]);
|
world_chunk_mark_dirty(world.chunk_mapping[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void world_chunk_replace_outer_block(ecs_world_t *ecs, int64_t id, uint16_t block_idx, uint8_t block_id) {
|
void world_chunk_replace_outer_block(int64_t id, uint16_t block_idx, uint8_t block_id) {
|
||||||
ZPL_ASSERT(block_idx >= 0 && block_idx < zpl_square(world.chunk_size));
|
ZPL_ASSERT(block_idx >= 0 && block_idx < zpl_square(world.chunk_size));
|
||||||
world.outer_block_mapping[id][block_idx] = block_id;
|
world.outer_block_mapping[id][block_idx] = block_id;
|
||||||
world_chunk_mark_dirty(ecs, world.chunk_mapping[id]);
|
world_chunk_mark_dirty(world.chunk_mapping[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *world_chunk_get_blocks(int64_t id) {
|
uint8_t *world_chunk_get_blocks(int64_t id) {
|
||||||
return world.block_mapping[id];
|
return world.block_mapping[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
void world_chunk_mark_dirty(ecs_world_t *ecs, ecs_entity_t e) {
|
void world_chunk_mark_dirty(ecs_entity_t e) {
|
||||||
bool was_added=false;
|
bool was_added=false;
|
||||||
Chunk *chunk = ecs_get_mut(ecs, e, Chunk, &was_added);
|
Chunk *chunk = ecs_get_mut(world_ecs(), e, Chunk, &was_added);
|
||||||
ZPL_ASSERT(!was_added);
|
ZPL_ASSERT(!was_added);
|
||||||
if (chunk) chunk->is_dirty = true;
|
if (chunk) chunk->is_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t world_chunk_is_dirty(ecs_world_t *ecs, ecs_entity_t e) {
|
uint8_t world_chunk_is_dirty(ecs_entity_t e) {
|
||||||
bool was_added=false;
|
bool was_added=false;
|
||||||
Chunk *chunk = ecs_get_mut(ecs, e, Chunk, &was_added);
|
Chunk *chunk = ecs_get_mut(world_ecs(), e, Chunk, &was_added);
|
||||||
ZPL_ASSERT(!was_added);
|
ZPL_ASSERT(!was_added);
|
||||||
if (chunk) return chunk->is_dirty;
|
if (chunk) return chunk->is_dirty;
|
||||||
return false;
|
return false;
|
||||||
|
@ -445,5 +467,5 @@ int64_t *world_chunk_query_entities(int64_t e, size_t *ents_len, int8_t radius)
|
||||||
|
|
||||||
uint8_t world_entity_valid(ecs_entity_t e) {
|
uint8_t world_entity_valid(ecs_entity_t e) {
|
||||||
if (!e) return false;
|
if (!e) return false;
|
||||||
return ecs_is_alive(world.ecs, e);
|
return ecs_is_alive(world_ecs(), e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ typedef struct {
|
||||||
uint64_t tracker_update[3];
|
uint64_t tracker_update[3];
|
||||||
uint8_t active_layer_id;
|
uint8_t active_layer_id;
|
||||||
ecs_world_t *ecs;
|
ecs_world_t *ecs;
|
||||||
|
ecs_world_t *ecs_stage;
|
||||||
ecs_query_t *ecs_update;
|
ecs_query_t *ecs_update;
|
||||||
ecs_entity_t *chunk_mapping;
|
ecs_entity_t *chunk_mapping;
|
||||||
librg_world *tracker;
|
librg_world *tracker;
|
||||||
|
@ -54,7 +55,8 @@ int32_t world_read(void* data, uint32_t datalen, void *udata);
|
||||||
int32_t world_write(pkt_header *pkt, void *udata);
|
int32_t world_write(pkt_header *pkt, void *udata);
|
||||||
|
|
||||||
uint32_t world_buf(uint8_t const **ptr, uint32_t *width);
|
uint32_t world_buf(uint8_t const **ptr, uint32_t *width);
|
||||||
ecs_world_t *world_ecs(void); // TODO(zaklaus): add staging support
|
ecs_world_t *world_ecs(void);
|
||||||
|
void world_set_stage(ecs_world_t *ecs);
|
||||||
librg_world *world_tracker(void);
|
librg_world *world_tracker(void);
|
||||||
|
|
||||||
uint16_t world_chunk_size(void);
|
uint16_t world_chunk_size(void);
|
||||||
|
@ -74,11 +76,11 @@ world_block_lookup world_block_from_realpos(float x, float y);
|
||||||
world_block_lookup world_block_from_index(int64_t id, uint16_t block_idx);
|
world_block_lookup world_block_from_index(int64_t id, uint16_t block_idx);
|
||||||
int64_t world_chunk_from_realpos(float x, float y);
|
int64_t world_chunk_from_realpos(float x, float y);
|
||||||
int64_t world_chunk_from_entity(ecs_entity_t id);
|
int64_t world_chunk_from_entity(ecs_entity_t id);
|
||||||
void world_chunk_replace_block(ecs_world_t *ecs, int64_t id, uint16_t block_idx, uint8_t block_id);
|
void world_chunk_replace_block(int64_t id, uint16_t block_idx, uint8_t block_id);
|
||||||
void world_chunk_replace_outer_block(ecs_world_t *ecs, int64_t id, uint16_t block_idx, uint8_t block_id);
|
void world_chunk_replace_outer_block(int64_t id, uint16_t block_idx, uint8_t block_id);
|
||||||
uint8_t *world_chunk_get_blocks(int64_t id);
|
uint8_t *world_chunk_get_blocks(int64_t id);
|
||||||
void world_chunk_mark_dirty(ecs_world_t *ecs, ecs_entity_t e);
|
void world_chunk_mark_dirty(ecs_entity_t e);
|
||||||
uint8_t world_chunk_is_dirty(ecs_world_t *ecs, ecs_entity_t e);
|
uint8_t world_chunk_is_dirty(ecs_entity_t e);
|
||||||
|
|
||||||
// NOTE(zaklaus): Uses locally persistent buffer !!
|
// NOTE(zaklaus): Uses locally persistent buffer !!
|
||||||
int64_t *world_chunk_fetch_entities(librg_chunk chunk_id, size_t *ents_len);
|
int64_t *world_chunk_fetch_entities(librg_chunk chunk_id, size_t *ents_len);
|
||||||
|
|
|
@ -12,6 +12,7 @@ ECS_COMPONENT_DECLARE(Classify);
|
||||||
ECS_COMPONENT_DECLARE(Vehicle);
|
ECS_COMPONENT_DECLARE(Vehicle);
|
||||||
ECS_COMPONENT_DECLARE(IsInVehicle);
|
ECS_COMPONENT_DECLARE(IsInVehicle);
|
||||||
ECS_COMPONENT_DECLARE(ItemDrop);
|
ECS_COMPONENT_DECLARE(ItemDrop);
|
||||||
|
ECS_COMPONENT_DECLARE(Inventory);
|
||||||
ECS_TAG_DECLARE(EcsActor);
|
ECS_TAG_DECLARE(EcsActor);
|
||||||
ECS_TAG_DECLARE(EcsDemoNPC);
|
ECS_TAG_DECLARE(EcsDemoNPC);
|
||||||
ECS_TYPE_DECLARE(Player);
|
ECS_TYPE_DECLARE(Player);
|
||||||
|
@ -37,6 +38,7 @@ void ComponentsImport(ecs_world_t *ecs) {
|
||||||
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, IsInVehicle);
|
ECS_COMPONENT_DEFINE(ecs, IsInVehicle);
|
||||||
ECS_COMPONENT_DEFINE(ecs, ItemDrop);
|
ECS_COMPONENT_DEFINE(ecs, ItemDrop);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, Inventory);
|
||||||
|
|
||||||
ECS_TAG_DEFINE(ecs, Walking);
|
ECS_TAG_DEFINE(ecs, Walking);
|
||||||
ECS_TAG_DEFINE(ecs, Flying);
|
ECS_TAG_DEFINE(ecs, Flying);
|
||||||
|
@ -59,6 +61,7 @@ void ComponentsImport(ecs_world_t *ecs) {
|
||||||
ECS_SET_COMPONENT(Vehicle);
|
ECS_SET_COMPONENT(Vehicle);
|
||||||
ECS_SET_COMPONENT(IsInVehicle);
|
ECS_SET_COMPONENT(IsInVehicle);
|
||||||
ECS_SET_COMPONENT(ItemDrop);
|
ECS_SET_COMPONENT(ItemDrop);
|
||||||
|
ECS_SET_COMPONENT(Inventory);
|
||||||
ECS_SET_ENTITY(Walking);
|
ECS_SET_ENTITY(Walking);
|
||||||
ECS_SET_ENTITY(Flying);
|
ECS_SET_ENTITY(Flying);
|
||||||
ECS_SET_ENTITY(EcsActor);
|
ECS_SET_ENTITY(EcsActor);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "flecs/flecs.h"
|
#include "flecs/flecs.h"
|
||||||
#include "flecs/flecs_meta.h"
|
#include "flecs/flecs_meta.h"
|
||||||
#include "items.h"
|
|
||||||
|
|
||||||
//NOTE(zaklaus): custom macro to define meta components outside the current scope
|
//NOTE(zaklaus): custom macro to define meta components outside the current scope
|
||||||
|
|
||||||
|
@ -16,6 +15,8 @@ ecs_new_meta(world, ecs_entity(T), &__##T##__);
|
||||||
(ecs_get(world, entity, component) ? ecs_get_mut(world, entity, component, NULL) : NULL)
|
(ecs_get(world, entity, component) ? ecs_get_mut(world, entity, component, NULL) : NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ITEMS_INVENTORY_SIZE 9
|
||||||
|
|
||||||
ECS_STRUCT(Vector2D, {
|
ECS_STRUCT(Vector2D, {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
|
@ -38,9 +39,19 @@ ECS_ALIAS(Vector2D, Velocity);
|
||||||
ECS_STRUCT(Input, {
|
ECS_STRUCT(Input, {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
|
float mx;
|
||||||
|
float my;
|
||||||
uint8_t use;
|
uint8_t use;
|
||||||
uint8_t sprint;
|
uint8_t sprint;
|
||||||
|
uint8_t ctrl;
|
||||||
uint8_t is_blocked;
|
uint8_t is_blocked;
|
||||||
|
|
||||||
|
// NOTE(zaklaus): inventory
|
||||||
|
uint8_t selected_item;
|
||||||
|
uint8_t drop;
|
||||||
|
uint8_t swap;
|
||||||
|
uint8_t swap_from;
|
||||||
|
uint8_t swap_to;
|
||||||
});
|
});
|
||||||
|
|
||||||
ECS_STRUCT(ClientInfo, {
|
ECS_STRUCT(ClientInfo, {
|
||||||
|
@ -78,10 +89,15 @@ typedef struct {
|
||||||
} IsInVehicle;
|
} IsInVehicle;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
item_kind kind;
|
uint16_t kind;
|
||||||
uint32_t quantity;
|
uint32_t quantity;
|
||||||
} ItemDrop;
|
} ItemDrop;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ItemDrop items[ITEMS_INVENTORY_SIZE];
|
||||||
|
float pickup_time;
|
||||||
|
} Inventory;
|
||||||
|
|
||||||
ECS_COMPONENT_EXTERN(Chunk);
|
ECS_COMPONENT_EXTERN(Chunk);
|
||||||
ECS_COMPONENT_EXTERN(Position);
|
ECS_COMPONENT_EXTERN(Position);
|
||||||
ECS_COMPONENT_EXTERN(Vector2D);
|
ECS_COMPONENT_EXTERN(Vector2D);
|
||||||
|
@ -94,6 +110,7 @@ ECS_COMPONENT_EXTERN(Classify);
|
||||||
ECS_COMPONENT_EXTERN(Vehicle);
|
ECS_COMPONENT_EXTERN(Vehicle);
|
||||||
ECS_COMPONENT_EXTERN(IsInVehicle);
|
ECS_COMPONENT_EXTERN(IsInVehicle);
|
||||||
ECS_COMPONENT_EXTERN(ItemDrop);
|
ECS_COMPONENT_EXTERN(ItemDrop);
|
||||||
|
ECS_COMPONENT_EXTERN(Inventory);
|
||||||
ECS_TAG_EXTERN(EcsActor);
|
ECS_TAG_EXTERN(EcsActor);
|
||||||
ECS_TAG_EXTERN(EcsDemoNPC);
|
ECS_TAG_EXTERN(EcsDemoNPC);
|
||||||
ECS_TYPE_EXTERN(Player);
|
ECS_TYPE_EXTERN(Player);
|
||||||
|
@ -116,6 +133,7 @@ typedef struct {
|
||||||
ECS_DECLARE_COMPONENT(Vehicle);
|
ECS_DECLARE_COMPONENT(Vehicle);
|
||||||
ECS_DECLARE_COMPONENT(IsInVehicle);
|
ECS_DECLARE_COMPONENT(IsInVehicle);
|
||||||
ECS_DECLARE_COMPONENT(ItemDrop);
|
ECS_DECLARE_COMPONENT(ItemDrop);
|
||||||
|
ECS_DECLARE_COMPONENT(Inventory);
|
||||||
ECS_DECLARE_ENTITY(EcsActor);
|
ECS_DECLARE_ENTITY(EcsActor);
|
||||||
ECS_DECLARE_ENTITY(EcsDemoNPC);
|
ECS_DECLARE_ENTITY(EcsDemoNPC);
|
||||||
ECS_DECLARE_TYPE(Player);
|
ECS_DECLARE_TYPE(Player);
|
||||||
|
@ -139,6 +157,7 @@ ECS_IMPORT_COMPONENT(handles, Classify);\
|
||||||
ECS_IMPORT_COMPONENT(handles, Vehicle);\
|
ECS_IMPORT_COMPONENT(handles, Vehicle);\
|
||||||
ECS_IMPORT_COMPONENT(handles, IsInVehicle);\
|
ECS_IMPORT_COMPONENT(handles, IsInVehicle);\
|
||||||
ECS_IMPORT_COMPONENT(handles, ItemDrop);\
|
ECS_IMPORT_COMPONENT(handles, ItemDrop);\
|
||||||
|
ECS_IMPORT_COMPONENT(handles, Inventory);\
|
||||||
ECS_IMPORT_TYPE(handles, Player);\
|
ECS_IMPORT_TYPE(handles, Player);\
|
||||||
ECS_IMPORT_TYPE(handles, Builder);\
|
ECS_IMPORT_TYPE(handles, Builder);\
|
||||||
ECS_IMPORT_TYPE(handles, Movement);\
|
ECS_IMPORT_TYPE(handles, Movement);\
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "source/system_onfoot.c"
|
#include "source/system_onfoot.c"
|
||||||
#include "source/system_demo.c"
|
#include "source/system_demo.c"
|
||||||
#include "source/system_vehicle.c"
|
#include "source/system_vehicle.c"
|
||||||
|
#include "source/system_items.c"
|
||||||
|
|
||||||
inline float physics_correction(float x, float vx, float bounce) {
|
inline float physics_correction(float x, float vx, float bounce) {
|
||||||
float r = (((zpl_max(0.0f, (WORLD_BLOCK_SIZE/2.0f) - zpl_abs(x))*zpl_sign(x)))*(WORLD_BLOCK_SIZE/2.0f));
|
float r = (((zpl_max(0.0f, (WORLD_BLOCK_SIZE/2.0f) - zpl_abs(x))*zpl_sign(x)))*(WORLD_BLOCK_SIZE/2.0f));
|
||||||
|
@ -131,9 +132,19 @@ void ApplyWorldDragOnVelocity(ecs_iter_t *it) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnableWorldEdit(ecs_iter_t *it) {
|
||||||
|
world_set_stage(it->world);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisableWorldEdit(ecs_iter_t *it) {
|
||||||
|
(void)it;
|
||||||
|
world_set_stage(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void SystemsImport(ecs_world_t *ecs) {
|
void SystemsImport(ecs_world_t *ecs) {
|
||||||
ECS_MODULE(ecs, Systems);
|
ECS_MODULE(ecs, Systems);
|
||||||
|
|
||||||
|
ECS_SYSTEM(ecs, EnableWorldEdit, EcsOnLoad);
|
||||||
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, components.Input, components.Velocity, components.Position, !components.IsInVehicle);
|
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, components.Input, components.Velocity, components.Position, !components.IsInVehicle);
|
||||||
ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, components.Velocity, components.EcsDemoNPC);
|
ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, components.Velocity, components.EcsDemoNPC);
|
||||||
|
|
||||||
|
@ -146,10 +157,16 @@ void SystemsImport(ecs_world_t *ecs) {
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, EnterVehicle, EcsPostUpdate, components.Input, components.Position, !components.IsInVehicle);
|
ECS_SYSTEM(ecs, EnterVehicle, EcsPostUpdate, components.Input, components.Position, !components.IsInVehicle);
|
||||||
ECS_SYSTEM(ecs, LeaveVehicle, EcsPostUpdate, components.Input, components.IsInVehicle, components.Velocity);
|
ECS_SYSTEM(ecs, LeaveVehicle, EcsPostUpdate, components.Input, components.IsInVehicle, components.Velocity);
|
||||||
ECS_SYSTEM(ecs, DemoPlaceIceBlock, EcsPostUpdate, components.Input, components.Position, !components.IsInVehicle);
|
|
||||||
|
ECS_SYSTEM(ecs, PickItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
|
||||||
|
ECS_SYSTEM(ecs, DropItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
|
||||||
|
ECS_SYSTEM(ecs, SwapItems, EcsPostUpdate, components.Input, components.Inventory);
|
||||||
|
ECS_SYSTEM(ecs, UseItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position, components.Velocity);
|
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position, components.Velocity);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);
|
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);
|
||||||
|
|
||||||
|
ECS_SYSTEM(ecs, DisableWorldEdit, EcsPostUpdate);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ void DemoPlaceIceBlock(ecs_iter_t *it) {
|
||||||
if (in[i].use) {
|
if (in[i].use) {
|
||||||
in[i].use = false;
|
in[i].use = false;
|
||||||
world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y);
|
world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y);
|
||||||
world_chunk_replace_outer_block(it->world, l.chunk_id, l.id, watr_id);
|
world_chunk_replace_outer_block(l.chunk_id, l.id, watr_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
#include "items.h"
|
||||||
|
|
||||||
|
#define ITEM_PICK_RADIUS 25.0f
|
||||||
|
#define ITEM_ATTRACT_RADIUS 75.0f
|
||||||
|
#define ITEM_ATTRACT_FORCE 0.63f
|
||||||
|
|
||||||
|
void PickItem(ecs_iter_t *it) {
|
||||||
|
Position *p = ecs_column(it, Position, 2);
|
||||||
|
Inventory *inv = ecs_column(it, Inventory, 3);
|
||||||
|
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < ents_count; j++) {
|
||||||
|
ItemDrop *drop = 0;
|
||||||
|
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||||
|
Position *p2 = ecs_get_mut(it->world, ents[j], Position, NULL);
|
||||||
|
|
||||||
|
float dx = p2->x - p[i].x;
|
||||||
|
float dy = p2->y - p[i].y;
|
||||||
|
float range = zpl_sqrt(dx*dx + dy*dy);
|
||||||
|
if (range <= ITEM_PICK_RADIUS) {
|
||||||
|
for (size_t k = 0; k < ITEMS_INVENTORY_SIZE; k += 1) {
|
||||||
|
ItemDrop *item = &inv[i].items[k];
|
||||||
|
uint16_t item_id = item_find(item->kind);
|
||||||
|
if ((item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(item_id)) {
|
||||||
|
uint32_t picked_count = zpl_max(0, drop->quantity);
|
||||||
|
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(item_id) - item->quantity);
|
||||||
|
item->quantity += picked_count;
|
||||||
|
drop->quantity -= picked_count;
|
||||||
|
|
||||||
|
if (drop->quantity == 0)
|
||||||
|
item_despawn(ents[j]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (range <= ITEM_ATTRACT_RADIUS) {
|
||||||
|
p2->x = zpl_lerp(p2->x, p[i].x, ITEM_ATTRACT_FORCE*it->delta_time);
|
||||||
|
p2->y = zpl_lerp(p2->y, p[i].y, ITEM_ATTRACT_FORCE*it->delta_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ITEM_DROP_PICKUP_TIME 2.5f
|
||||||
|
|
||||||
|
void DropItem(ecs_iter_t *it) {
|
||||||
|
Input *in = ecs_column(it, Input, 1);
|
||||||
|
Position *p = ecs_column(it, Position, 2);
|
||||||
|
Inventory *inv = ecs_column(it, Inventory, 3);
|
||||||
|
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
if (!in[i].drop) continue;
|
||||||
|
|
||||||
|
ItemDrop *item = &inv[i].items[in[i].selected_item];
|
||||||
|
|
||||||
|
if (item->quantity <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool is_item_nearby = false;
|
||||||
|
|
||||||
|
size_t ents_count;
|
||||||
|
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < ents_count; j++) {
|
||||||
|
ItemDrop *drop = 0;
|
||||||
|
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||||
|
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 <= ITEM_PICK_RADIUS) {
|
||||||
|
if (item->kind == drop->kind) {
|
||||||
|
uint32_t dropped_count = item->quantity;
|
||||||
|
if (in[i].sprint) {
|
||||||
|
dropped_count /= 2;
|
||||||
|
} else if (in[i].ctrl) {
|
||||||
|
dropped_count = 1;
|
||||||
|
}
|
||||||
|
drop->quantity += dropped_count;
|
||||||
|
item->quantity -= dropped_count;
|
||||||
|
is_item_nearby = true;
|
||||||
|
inv[i].pickup_time = game_time() + ITEM_DROP_PICKUP_TIME;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_item_nearby) {
|
||||||
|
uint32_t dropped_count = item->quantity;
|
||||||
|
if (in[i].sprint) {
|
||||||
|
dropped_count /= 2;
|
||||||
|
} else if (in[i].ctrl) {
|
||||||
|
dropped_count = 1;
|
||||||
|
}
|
||||||
|
ecs_entity_t te = item_spawn(item->kind, dropped_count);
|
||||||
|
item->quantity -= dropped_count;
|
||||||
|
|
||||||
|
Position *ipos = ecs_get_mut(it->world, te, Position, NULL);
|
||||||
|
*ipos = p[i];
|
||||||
|
|
||||||
|
Velocity *v = ecs_get_mut(it->world, te, Velocity, NULL);
|
||||||
|
v->x = in[i].mx * 800.0f;
|
||||||
|
v->y = in[i].my * 800.0f;
|
||||||
|
|
||||||
|
inv[i].pickup_time = game_time() + ITEM_DROP_PICKUP_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
in[i].drop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapItems(ecs_iter_t *it) {
|
||||||
|
Input *in = ecs_column(it, Input, 1);
|
||||||
|
Inventory *inv = ecs_column(it, Inventory, 2);
|
||||||
|
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
if (!in[i].swap) continue;
|
||||||
|
|
||||||
|
ItemDrop *to = &inv[i].items[in[i].swap_to];
|
||||||
|
ItemDrop *from = &inv[i].items[in[i].swap_from];
|
||||||
|
uint16_t to_id = item_find(to->kind);
|
||||||
|
|
||||||
|
if (to == from) {
|
||||||
|
// NOTE(zaklaus): do nothing
|
||||||
|
} else if (to->kind == from->kind && to->quantity > 0) {
|
||||||
|
uint32_t swapped_count = from->quantity;
|
||||||
|
if (in[i].sprint) {
|
||||||
|
swapped_count /= 2;
|
||||||
|
} else if (in[i].ctrl) {
|
||||||
|
swapped_count = 1;
|
||||||
|
}
|
||||||
|
swapped_count = zpl_clamp(swapped_count, 0, item_max_quantity(to_id) - to->quantity);
|
||||||
|
to->quantity += swapped_count;
|
||||||
|
from->quantity -= swapped_count;
|
||||||
|
|
||||||
|
if (swapped_count == 0) {
|
||||||
|
ItemDrop tmp = *to;
|
||||||
|
*to = *from;
|
||||||
|
*from = tmp;
|
||||||
|
}
|
||||||
|
} else if ((in[i].ctrl || in[i].sprint) && to->quantity == 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;
|
||||||
|
from->quantity -= split_count;
|
||||||
|
to->kind = from->kind;
|
||||||
|
} else {
|
||||||
|
ItemDrop tmp = *to;
|
||||||
|
*to = *from;
|
||||||
|
*from = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
in[i].swap = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UseItem(ecs_iter_t *it) {
|
||||||
|
Input *in = ecs_column(it, Input, 1);
|
||||||
|
Position *p = ecs_column(it, Position, 2);
|
||||||
|
Inventory *inv = ecs_column(it, Inventory, 3);
|
||||||
|
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
if (!in[i].use) continue;
|
||||||
|
|
||||||
|
ItemDrop *item = &inv[i].items[in[i].selected_item];
|
||||||
|
if (!item || item->quantity <= 0) continue;
|
||||||
|
item_use(it->world, item, p[i]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue