Compare commits

..

4 Commits

Author SHA1 Message Date
Dominik Madarász 082c485eeb billboarding 2022-10-15 22:33:09 +02:00
Vladyslav Hrytsenko 76dd148671 added mega tree 2022-10-15 20:44:41 +03:00
Vladyslav Hrytsenko b8e27c9b0d updated furnace 2022-10-15 19:01:22 +03:00
Vladyslav Hrytsenko f60cb28d00 code: added new things 2022-10-15 15:52:20 +03:00
253 changed files with 23530 additions and 338708 deletions

View File

@ -1,22 +0,0 @@
name: Build web and deploy
on:
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
BUTLER_API_KEY: ${{ secrets.BUTLER_KEY }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up emsdk
run: web/setup.sh
- name: Build and deploy eco2d
run: web/deploy.sh

8
.gitignore vendored
View File

@ -1,6 +1,6 @@
build build
build.* build_rel
build_* build_web
emsdk emsdk
deploy_web deploy_web
run_web run_web
@ -20,7 +20,3 @@ GTAGS
pkg pkg
pkg.zip pkg.zip
eco2d.zip eco2d.zip
eco2d.db
eco2d.sublime-workspace
.cache

View File

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

View File

@ -1,6 +1,6 @@
<h1> <div align="center">
eco2d <a href="https://zaklaus.itch.io/eco2d"><img src="https://user-images.githubusercontent.com/2182108/111983468-d5593e80-8b12-11eb-9c59-8c78ecc0504e.png" alt="eco2d" /></a>
</h1> </div>
<br /> <br />
@ -23,7 +23,7 @@
</div> </div>
# Introduction # Introduction
eco2d is a experimental set of games made out of curiosity. It attempts to bridge several libraries to create a playable sandbox with ease of extensibility and with performance in mind. The goal is not to make a generic 2D game engine but to build a game prototype that anyone can use to build various experiments. zpl.eco2d is a small framework/game engine made out of curiosity. It attempts to bridge several libraries to create a playable sandbox with ease of extensibility and with performance in mind. The goal is not to make a generic 2D game engine but to build a game prototype that anyone can use to build various experiments.
The game runs on top of [raylib](https://raylib.com/) technologies and makes use of the [zpl](https://zpl.pw/) ecosystem alongside the **cwpack** library for data serialization. The game logic and lifecycle are maintained using [flecs](https://github.com/SanderMertens/flecs/) library and its suite of tools that help us improve the development efficiency. The game runs on top of [raylib](https://raylib.com/) technologies and makes use of the [zpl](https://zpl.pw/) ecosystem alongside the **cwpack** library for data serialization. The game logic and lifecycle are maintained using [flecs](https://github.com/SanderMertens/flecs/) library and its suite of tools that help us improve the development efficiency.
@ -31,7 +31,7 @@ It was built with networked game sessions in mind from the ground up and therefo
* Networked game (UDP) - networked sessions benefit from the use of [enet](https://github.com/zpl-c/enet/) library. * Networked game (UDP) - networked sessions benefit from the use of [enet](https://github.com/zpl-c/enet/) library.
* Local Only sessions - Data is streamed via local buffers. * Local Only sessions - Data is streamed via local buffers.
In both cases, the game engine does not differentiate between these two options and makes the concept of Server<>client infrastructure entirely abstract. As a result, gameplay logic is only tied to living entities, where the entity might represent a networked client / local controller. In both cases, the game engine does not differentiate between these two options and makes the concept of Server <>client infrastructure entirely abstract. As a result, gameplay logic is only tied to living entities, where the entity might represent a networked client / local controller.
All data is transferred via packets fully automated by our serialization rule system, which uses the **cwpack** library in the background. All data is transferred via packets fully automated by our serialization rule system, which uses the **cwpack** library in the background.
@ -90,7 +90,7 @@ build\eco2d.exe -?
``` ```
# License # License
eco2d code is licensed under the BSD 3-Clause license, as seen [here](LICENSE). zpl.eco2d code is licensed under the BSD 3-Clause license, as seen [here](LICENSE).
Assets under the **art** folder are released into [Public Domain](https://creativecommons.org/share-your-work/public-domain/cc0/) unless otherwise stated. Assets under the **art** folder are released into [Public Domain](https://creativecommons.org/share-your-work/public-domain/cc0/) unless otherwise stated.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 B

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 B

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 901 B

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 254 B

View File

@ -1,28 +0,0 @@
-- typedef enum {
-- BLOCK_FLAG_COLLISION = (1 << 1),
-- BLOCK_FLAG_HAZARD = (1 << 2),
-- BLOCK_FLAG_ESSENTIAL = (1 << 3),
-- BLOCK_FLAG_DESTROY_ON_COLLISION = (1 << 4),
-- BLOCK_FLAG_ENTITY = (1 << 5),
-- } block_flags;
INSERT INTO blocks (kind, flags, drag, friction, bounce, velx, vely) VALUES
(asset('EMPTY'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('GROUND'), NULL, 1.0, 1.0, NULL, NULL, NULL),
(asset('DIRT'), NULL, 2.1, 1.0, NULL, NULL, NULL),
(asset('WALL'), (1<<1), 1.0, 1.0, 1.0, NULL, NULL),
(asset('HILL'), (1<<1), 1.0, 1.0, NULL, NULL, NULL),
(asset('HILL_SNOW'), (1<<1), 1.0, 1.0, NULL, NULL, NULL),
(asset('WATER'), 0, 0.11, 1.0, NULL, NULL, NULL),
(asset('LAVA'), (1<<2), 6.2, 4.0, NULL, NULL, NULL),
(asset('FENCE'), (1<<1), 1.0, 1.0, 1.0, NULL, NULL),
(asset('WOOD'), (1<<1), 1.0, 1.0, 0.0, NULL, NULL),
(asset('TREE'), (1<<1)|(1<<4), 1.0, 1.0, 0.0, NULL, NULL),
(asset('CHEST'), (1<<5), NULL, NULL, NULL, NULL, NULL),
(asset('FURNACE'), (1<<5), NULL, NULL, NULL, NULL, NULL),
(asset('TEST_TALL'), (1<<1), NULL, NULL, NULL, NULL, NULL),
(asset('BELT_LEFT'), NULL, 1.0, 1.0, NULL, -150.0, NULL),
(asset('BELT_RIGHT'), NULL, 1.0, 1.0, NULL, 150.0, NULL),
(asset('BELT_UP'), NULL, 1.0, 1.0, NULL, NULL, -150.0),
(asset('BELT_DOWN'), NULL, 1.0, 1.0, NULL, NULL, 150.0);

View File

@ -1,46 +0,0 @@
-- typedef enum {
-- // NOTE(zaklaus): hardcoded fields for placement ops
-- UKIND_DELETE,
-- UKIND_PLACE,
-- UKIND_PLACE_ITEM,
-- UKIND_PLACE_ITEM_DATA,
-- UKIND_END_PLACE,
--
-- // NOTE(zaklaus): the rest of possible actions
-- UKIND_HOLD,
-- UKIND_PROXY,
-- } item_usage;
--
-- typedef enum {
-- UDATA_NONE,
-- UDATA_ENERGY_SOURCE,
-- } item_attachment;
INSERT INTO items (kind, usage, attachment, max_quantity, place_kind, directional,
proxy_id, place_item_id, producer, energy_level, blueprint_w, blueprint_h, blueprint_plan)
VALUES
(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('FENCE'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('COAL'), 5, 1, 64, NULL, NULL, NULL, NULL, asset('FURNACE'), 15.0, NULL, NULL, NULL),
(asset('WOOD'), 1, 0, 64, asset('WOOD'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('TREE'), 1, 0, 64, asset('TREE'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('TEST_TALL'), 1, 0, 64, asset('TEST_TALL'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT'), 1, 0, 999, asset('BELT'), 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT_LEFT'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT_RIGHT'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT_UP'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('BELT_DOWN'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
(asset('CHEST'), 2, 0, 32, NULL, NULL, NULL, asset('CHEST'), NULL, NULL, NULL, NULL, NULL),
(asset('CRAFTBENCH'), 2, 0, 32, NULL, NULL, NULL, asset('CRAFTBENCH'), NULL, NULL, NULL, NULL, NULL),
(asset('FURNACE'), 2, 0, 32, NULL, NULL, NULL, asset('FURNACE'), NULL, NULL, NULL, NULL, NULL),
(asset('SPLITTER'), 2, 0, 32, NULL, NULL, NULL, asset('SPLITTER'), NULL, NULL, NULL, NULL, NULL),
(asset('ASSEMBLER'), 2, 0, 32, NULL, NULL, NULL, asset('ASSEMBLER'), NULL, NULL, NULL, NULL, NULL),
(asset('CREATURE'), 2, 0, 32, NULL, NULL, NULL, asset('CREATURE'), NULL, NULL, NULL, NULL, NULL),
(asset('IRON_ORE'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('IRON_INGOT'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('IRON_PLATES'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('SCREWS'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('LOG'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(asset('PLANK'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-- (asset('BLUEPRINT_DEMO_HOUSE'), 3, 0, 1, NULL, NULL, NULL, asset('BLUEPRINT'), NULL, NULL, 4, 4, ''),
(asset('CREATURE_FOOD'), 5, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

View File

@ -1 +0,0 @@
Only modify these for eco2d game specifically!

View File

@ -1,18 +0,0 @@
INSERT INTO recipes (product, product_qty, process_ticks, producer) VALUES
(asset('IRON_PLATES'), 4, 20, asset('FURNACE')),
(asset('SCREWS'), 8, 40, asset('CRAFTBENCH')),
(asset('BELT'), 1, 120, asset('ASSEMBLER'));
INSERT INTO reagents (asset_id, qty) VALUES
(asset('IRON_ORE'), 1),
(asset('IRON_PLATES'), 1),
(asset('FENCE'), 1),
(asset('SCREWS'), 4),
(asset('IRON_PLATES'), 2);
INSERT INTO recipe_reagents (recipe_id, reagent_id) VALUES
(1, 1),
(2, 2),
(3, 3),
(3, 4),
(3, 5);

View File

@ -1,42 +0,0 @@
INSERT INTO resources (asset, kind) VALUES
(asset('EMPTY'), 0),
(asset('BLANK'), 0),
(asset('BLOCK_FRAME'), 0),
(asset('BUILDMODE_HIGHLIGHT'), 0),
(asset('COAL'), 0),
(asset('IRON_ORE'), 0),
(asset('IRON_INGOT'), 0),
(asset('IRON_PLATES'), 0),
(asset('SCREWS'), 0),
(asset('LOG'), 0),
(asset('PLANK'), 0),
(asset('CHEST'), 0),
(asset('CREATURE'), 0),
(asset('CREATURE_FOOD'), 0),
(asset('FURNACE'), 0),
(asset('SPLITTER'), 0),
(asset('ASSEMBLER'), 0),
(asset('CRAFTBENCH'), 0),
(asset('BLUEPRINT'), 0),
(asset('BLUEPRINT_DEMO_HOUSE'), 0),
(asset('MOB'), 0),
(asset('PLAYER'), 0),
(asset('FENCE'), 0),
(asset('DEV'), 0),
(asset('GROUND'), 0),
(asset('DIRT'), 0),
(asset('WATER'), 2),
(asset('LAVA'), 0),
(asset('WALL'), 0),
(asset('HILL'), 0),
(asset('HILL_SNOW'), 0),
(asset('HOLE'), 0),
(asset('WOOD'), 0),
(asset('TEST_TALL'), 0),
(asset('TREE'), 0),
(asset('BELT'), 0),
(asset('BELT_LEFT'), 0),
(asset('BELT_RIGHT'), 0),
(asset('BELT_UP'), 0),
(asset('BELT_DOWN'), 0);

View File

@ -1,72 +0,0 @@
CREATE TABLE assets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(255) NOT NULL
);
CREATE TABLE resources (
id INTEGER PRIMARY KEY AUTOINCREMENT,
asset INTEGER NOT NULL,
kind INTEGER NOT NULL
);
CREATE TABLE blocks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
kind INTEGER NOT NULL,
flags INTEGER DEFAULT 0,
drag REAL,
friction REAL,
bounce REAL,
velx REAL,
vely REAL,
FOREIGN KEY (kind) REFERENCES assets(id)
);
CREATE TABLE items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
kind INTEGER NOT NULL,
usage INTEGER,
attachment INTEGER,
max_quantity INTEGER,
has_storage BOOLEAN,
place_kind INTEGER,
directional BOOLEAN,
proxy_id INTEGER,
place_item_id INTEGER,
producer INTEGER,
energy_level REAL,
blueprint_w INTEGER,
blueprint_h INTEGER,
blueprint_plan TEXT,
FOREIGN KEY (kind) REFERENCES assets(id)
);
CREATE TABLE reagents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
asset_id INTEGER NOT NULL,
qty INTEGER NOT NULL,
FOREIGN KEY (asset_id) REFERENCES assets(id)
);
CREATE TABLE recipes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
product INTEGER NOT NULL,
product_qty INTEGER NOT NULL,
process_ticks INTEGER NOT NULL,
producer INTEGER NOT NULL,
FOREIGN KEY (product) REFERENCES assets(id),
FOREIGN KEY (producer) REFERENCES assets(id)
);
CREATE TABLE recipe_reagents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
recipe_id INTEGER NOT NULL,
reagent_id INTEGER NOT NULL,
FOREIGN KEY (recipe_id) REFERENCES recipes(id),
FOREIGN KEY (reagent_id) REFERENCES reagents(id)
);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

View File

@ -1,3 +0,0 @@
@echo off
call win\setup_cl_generic.bat amd64
cmake --build build && build\eco2d

View File

@ -1,20 +1,20 @@
find_package(raylib 3.5 QUIET) find_package(raylib 3.5 QUIET)
if (NOT raylib_FOUND) if (NOT raylib_FOUND)
include(FetchContent) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
raylib raylib
URL https://github.com/zpl-c/raylib/archive/master.tar.gz URL https://github.com/zpl-c/raylib/archive/master.tar.gz
) )
FetchContent_GetProperties(raylib) FetchContent_GetProperties(raylib)
if (NOT raylib_POPULATED) if (NOT raylib_POPULATED)
set(FETCHCONTENT_QUIET NO) set(FETCHCONTENT_QUIET NO)
FetchContent_Populate(raylib) FetchContent_Populate(raylib)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR}) add_subdirectory(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR})
endif() endif()
endif() endif()

View File

@ -7,25 +7,25 @@ add_library(eco2d-foundation STATIC
src/platform/signal_handling.c src/platform/signal_handling.c
src/platform/profiler.c src/platform/profiler.c
src/platform/input.c
src/models/database.c
src/models/assets.c src/models/assets.c
src/models/components.c src/models/components.c
src/models/items.c src/models/items.c
src/models/entity.c src/models/entity.c
src/models/device.c src/models/device.c
src/models/crafting.c
src/models/prefabs/player.c src/models/prefabs/player.c
src/models/prefabs/vehicle.c src/models/prefabs/vehicle.c
src/models/prefabs/storage.c
src/models/prefabs/furnace.c
src/models/prefabs/blueprint.c
src/pkt/packet.c src/pkt/packet.c
src/gen/texgen_fallback.c src/gen/texgen_fallback.c
src/dev/debug_ui.c src/debug/debug_ui.c
src/dev/debug_draw.c src/debug/debug_draw.c
src/utils/options.c src/utils/options.c
src/utils/compress.c src/utils/compress.c
@ -46,6 +46,6 @@ add_library(eco2d-foundation STATIC
target_compile_definitions(eco2d-foundation PRIVATE CLIENT) target_compile_definitions(eco2d-foundation PRIVATE CLIENT)
include_directories(src ../modules ../../art/gen) include_directories(src ../modules ../../art/gen)
target_link_libraries(eco2d-foundation raylib raylib_nuklear cwpack flecs-bundle vendors-bundle) target_link_libraries(eco2d-foundation raylib cwpack flecs-bundle vendors-bundle)
link_system_libs(eco2d-foundation) link_system_libs(eco2d-foundation)

View File

@ -1,58 +0,0 @@
#pragma once
#define ASSET_INVALID 0xFF
#define _ASSETS\
X(ASSET_EMPTY)\
X(ASSET_BLANK)\
X(ASSET_BLOCK_FRAME)\
X(ASSET_BUILDMODE_HIGHLIGHT)\
X(ASSET_PLAYER)\
X(ASSET_THING)\
X(ASSET_CREATURE)\
X(ASSET_CREATURE_FOOD)\
X(ASSET_CHEST)\
X(ASSET_SPLITTER)\
X(ASSET_ASSEMBLER)\
X(ASSET_FURNACE)\
X(ASSET_CRAFTBENCH)\
X(ASSET_BLUEPRINT_BEGIN)\
X(ASSET_BLUEPRINT)\
X(ASSET_BLUEPRINT_DEMO_HOUSE)\
X(ASSET_BLUEPRINT_END)\
X(ASSET_FENCE)\
X(ASSET_DEV)\
X(ASSET_GROUND)\
X(ASSET_DIRT)\
X(ASSET_WATER)\
X(ASSET_LAVA)\
X(ASSET_WALL)\
X(ASSET_HILL)\
X(ASSET_HILL_SNOW)\
X(ASSET_HOLE)\
X(ASSET_WOOD)\
X(ASSET_TREE)\
X(ASSET_COAL)\
X(ASSET_IRON_ORE)\
X(ASSET_IRON_INGOT)\
X(ASSET_IRON_PLATES)\
X(ASSET_SCREWS)\
X(ASSET_LOG)\
X(ASSET_PLANK)\
X(ASSET_TEST_TALL)\
X(ASSET_BELT)\
X(ASSET_BELT_LEFT)\
X(ASSET_BELT_RIGHT)\
X(ASSET_BELT_UP)\
X(ASSET_BELT_DOWN)
typedef enum {
#define X(idx) idx,
_ASSETS
#undef X
MAX_INTERNAL_ASSETS,
NEXT_FREE_ASSET = MAX_INTERNAL_ASSETS,
MAX_ASSETS = 255
} asset_id;
extern const char *asset_names[];

View File

@ -3,7 +3,6 @@
#include "platform/platform.h" #include "platform/platform.h"
#include "world/world.h" #include "world/world.h"
#include "pkt/packet.h" #include "pkt/packet.h"
#include "models/database.h"
#include "platform/signal_handling.h" #include "platform/signal_handling.h"
#include "net/network.h" #include "net/network.h"
#include "models/entity.h" #include "models/entity.h"
@ -11,7 +10,6 @@
#include "world/entity_view.h" #include "world/entity_view.h"
#include "core/camera.h" #include "core/camera.h"
#include "platform/profiler.h" #include "platform/profiler.h"
#include "platform/renderer.h"
#include "flecs/flecs_os_api_stdcpp.h" #include "flecs/flecs_os_api_stdcpp.h"
#include "flecs.h" #include "flecs.h"
@ -23,19 +21,12 @@
#include "packets/pkt_01_welcome.h" #include "packets/pkt_01_welcome.h"
#include "packets/pkt_switch_viewer.h" #include "packets/pkt_switch_viewer.h"
#define RAYLIB_NUKLEAR_IMPLEMENTATION
ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0)
#include "raylib-nuklear.h"
ZPL_DIAGNOSTIC_POP
static uint8_t game_mode; static uint8_t game_mode;
static uint8_t game_should_close; static uint8_t game_should_close;
static world_view *world_viewers; static world_view *world_viewers;
static world_view *active_viewer; static world_view *active_viewer;
struct nk_context *game_ui = 0;
static WORLD_PKT_READER(pkt_reader) { static WORLD_PKT_READER(pkt_reader) {
pkt_header header = {0}; pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, data, datalen); uint32_t ok = pkt_header_decode(&header, data, datalen);
@ -101,7 +92,7 @@ void game_world_view_cycle_active(int8_t dir) {
game_world_view_set_active_by_idx(zpl_max(0, (idx+dir)%zpl_buffer_count(world_viewers))); game_world_view_set_active_by_idx(zpl_max(0, (idx+dir)%zpl_buffer_count(world_viewers)));
} }
void game_world_view_set_active_by_idx(uint16_t idx) { void game_world_view_set_active_by_idx(uint16_t idx) {
ZPL_ASSERT(idx < zpl_buffer_count(world_viewers)); ZPL_ASSERT(idx >= 0 && idx < zpl_buffer_count(world_viewers));
game_world_view_set_active(&world_viewers[idx]); game_world_view_set_active(&world_viewers[idx]);
} }
@ -134,12 +125,9 @@ float game_time() {
return (float)get_cached_time(); return (float)get_cached_time();
} }
void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) { void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) {
game_mode = play_mode; game_mode = play_mode;
game_should_close = false; game_should_close = false;
entity_default_spawnlist();
game_init(db_init());
#ifndef _DEBUG #ifndef _DEBUG
const char *host_ip = "lab.zakto.pw"; const char *host_ip = "lab.zakto.pw";
@ -159,9 +147,6 @@ void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num
world_viewers_init(num_viewers); world_viewers_init(num_viewers);
active_viewer = &world_viewers[0]; active_viewer = &world_viewers[0];
camera_reset(); camera_reset();
Font font = LoadFontEx("art/anonymous_pro_bold.ttf", 14, 0, 0);
game_ui = InitNuklearEx(font, 14);
} }
if (game_mode != GAMEKIND_SINGLE) { if (game_mode != GAMEKIND_SINGLE) {
@ -182,8 +167,6 @@ void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num
//ecs_set_target_fps(world_ecs(), 60); //ecs_set_target_fps(world_ecs(), 60);
} }
} }
game_init_ecs();
if (game_mode == GAMEKIND_SINGLE) { if (game_mode == GAMEKIND_SINGLE) {
for (uint32_t i = 0; i < num_viewers; i++) { for (uint32_t i = 0; i < num_viewers; i++) {
@ -197,7 +180,6 @@ int8_t game_is_networked() {
} }
void game_shutdown() { void game_shutdown() {
db_shutdown();
if (game_mode == GAMEKIND_CLIENT) { if (game_mode == GAMEKIND_CLIENT) {
network_client_disconnect(); network_client_disconnect();
@ -218,8 +200,7 @@ void game_shutdown() {
// TODO(zaklaus): crashes on exit // TODO(zaklaus): crashes on exit
//platform_shutdown(); //platform_shutdown();
UnloadNuklear(game_ui); }
}
} }
uint8_t game_is_running() { uint8_t game_is_running() {
@ -234,14 +215,13 @@ game_kind game_get_kind(void) {
return game_mode; return game_mode;
} }
void game_core_input() { void game_input() {
if (game_mode != GAMEKIND_HEADLESS) { if (game_mode != GAMEKIND_HEADLESS) {
platform_input(); platform_input();
UpdateNuklear(game_ui);
} }
} }
void game_core_update() { void game_update() {
static double last_update = 0.0f; static double last_update = 0.0f;
if (game_mode == GAMEKIND_CLIENT) { if (game_mode == GAMEKIND_CLIENT) {
network_client_tick(); network_client_tick();
@ -263,16 +243,12 @@ void game_core_update() {
last_update = get_cached_time(); last_update = get_cached_time();
} }
void game_core_render() { void game_render() {
if (game_mode != GAMEKIND_HEADLESS) { if (game_mode != GAMEKIND_HEADLESS) {
platform_render(); platform_render();
} }
} }
void game_draw_ui() {
DrawNuklear(game_ui);
}
void game_action_send_keystate(game_keystate_data *data) { void game_action_send_keystate(game_keystate_data *data) {
pkt_send_keystate_send(active_viewer->view_id, data); pkt_send_keystate_send(active_viewer->view_id, data);
} }
@ -291,71 +267,3 @@ void game_request_close() {
platform_request_close(); platform_request_close();
} }
} }
static game_world_render_entry* render_queue = NULL;
static void game__world_view_render_push_entry(uint64_t key, entity_view * data) {
if (!data) return;
if (data->kind == EKIND_CHUNK) {
world_view *view = game_world_view_get_active();
float size = (float)(view->chunk_size * WORLD_BLOCK_SIZE);
float offset = 0.0;
for (size_t ty = 0; ty < view->chunk_size; ty++) {
for (size_t tx = 0; tx < view->chunk_size; tx++) {
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
if (blk_id != 0) {
game_world_render_entry entry = {
.key = key,
.data = data,
.blk_id = blk_id,
.x = (data->x*size + offset) + (float)tx*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
.y = (data->y*size + offset) + (float)ty*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
.cy = (data->y*size + offset) + (float)ty*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
};
if (!(blocks_get_flags(blk_id) & BLOCK_FLAG_COLLISION)) {
entry.cy = ZPL_F32_MIN;
}
zpl_array_append(render_queue, entry);
}
}
}
return;
}
game_world_render_entry entry = {
.key = key,
.data = data,
.x = data->x,
.y = data->y,
.cy = data->y,
.blk_id = 0,
};
zpl_array_append(render_queue, entry);
}
static void game__world_view_render_ground(uint64_t key, entity_view * data) {
if (data->kind != EKIND_CHUNK) return;
renderer_draw_entry(key, data, 0);
}
void game_world_view_render_world(void) {
if (!render_queue) {
zpl_array_init(render_queue, zpl_heap());
}
zpl_array_clear(render_queue);
profile(PROF_RENDER_PUSH_AND_SORT_ENTRIES) {
game_world_view_active_entity_map(game__world_view_render_push_entry);
zpl_sort_array(render_queue, zpl_array_count(render_queue), zpl_f32_cmp(zpl_offset_of(game_world_render_entry, cy)));
}
game_world_view_active_entity_map(game__world_view_render_ground);
for (zpl_isize i = 0; i < zpl_array_count(render_queue); i++) {
renderer_draw_entry(render_queue[i].key, render_queue[i].data, &render_queue[i]);
}
}

View File

@ -2,7 +2,6 @@
#include "platform/system.h" #include "platform/system.h"
#include "world/world_view.h" #include "world/world_view.h"
#include "packets/pkt_send_keystate.h" #include "packets/pkt_send_keystate.h"
#include "packets/pkt_send_code.h"
typedef enum { typedef enum {
GAMEKIND_SINGLE, GAMEKIND_SINGLE,
@ -11,7 +10,7 @@ typedef enum {
FORCE_GAMEKIND_UINT8 = UINT8_MAX FORCE_GAMEKIND_UINT8 = UINT8_MAX
} game_kind; } game_kind;
void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled); void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled);
void game_shutdown(); void game_shutdown();
void game_request_close(); void game_request_close();
uint8_t game_is_running(); uint8_t game_is_running();
@ -20,24 +19,9 @@ float game_time();
game_kind game_get_kind(void); game_kind game_get_kind(void);
//~ NOTE(zaklaus): game events //~ NOTE(zaklaus): game events
// Implemented by games
void game_init(bool new_db);
void game_init_ecs(); // called once the world is initialised
void game_input(); void game_input();
void game_update(); void game_update();
void game_render(); void game_render();
void game_player_joined(uint64_t ent);
void game_player_departed(uint64_t ent);
void game_player_died(uint64_t ent);
void game_client_receive_code(pkt_send_code data);
// base methods called from games
void game_core_input();
void game_core_update();
void game_core_render();
//~ Called from platform.c
void game_draw_ui();
//~ NOTE(zaklaus): world view management //~ NOTE(zaklaus): world view management
world_view *game_world_view_get_active(void); world_view *game_world_view_get_active(void);
@ -48,7 +32,6 @@ 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); entity_view *game_world_view_active_get_entity(uint64_t ent_id);
void game_world_view_render_world(void);
//~ NOTE(zaklaus): viewer -> host actions //~ NOTE(zaklaus): viewer -> host actions
void game_action_send_keystate(game_keystate_data *data); void game_action_send_keystate(game_keystate_data *data);

View File

@ -5,6 +5,7 @@ typedef struct {
float phy_walk_drag; float phy_walk_drag;
uint64_t demo_npc_move_speed; uint64_t demo_npc_move_speed;
uint64_t demo_npc_steer_speed; uint64_t demo_npc_steer_speed;
float furnace_cook_time;
float item_pick_radius; float item_pick_radius;
float item_merger_radius; float item_merger_radius;
float item_attract_radius; float item_attract_radius;
@ -24,8 +25,6 @@ typedef struct {
float vehicle_brake_force; float vehicle_brake_force;
float veh_enter_radius; float veh_enter_radius;
float blueprint_build_time; float blueprint_build_time;
// survival rules
} game_rulesdef; } game_rulesdef;
extern game_rulesdef game_rules; extern game_rulesdef game_rules;

View File

@ -4,10 +4,11 @@ game_rulesdef game_rules = {
.phy_walk_drag = 4.23f, .phy_walk_drag = 4.23f,
.demo_npc_move_speed = 500, .demo_npc_move_speed = 500,
.demo_npc_steer_speed = 300, .demo_npc_steer_speed = 300,
.furnace_cook_time = 1.f,
.item_pick_radius = 25.0f, .item_pick_radius = 25.0f,
.item_merger_radius = 75.0f, .item_merger_radius = 75.0f,
.item_attract_radius = 75.0f, .item_attract_radius = 75.0f,
.item_attract_force = 1.98f, .item_attract_force = .98f,
.item_container_reach_radius = 105.0f, .item_container_reach_radius = 105.0f,
.item_drop_pickup_time = 2.5f, .item_drop_pickup_time = 2.5f,
.item_drop_merger_time = 6.5f, .item_drop_merger_time = 6.5f,

View File

@ -1,9 +1,9 @@
#include "dev/debug_draw.h" #include "debug/debug_draw.h"
#include "core/game.h" #include "core/game.h"
static debug_draw_queue draw_queue = {0}; static debug_draw_queue draw_queue = {0};
#if !defined(_DEBUG) || 0 #ifndef _DEBUG
static bool draw_is_enabled = false; static bool draw_is_enabled = false;
#else #else
static bool draw_is_enabled = true; static bool draw_is_enabled = true;

View File

@ -1,4 +1,4 @@
#include "dev/debug_replay.h" #include "debug/debug_replay.h"
#include "core/camera.h" #include "core/camera.h"
#include "models/entity.h" #include "models/entity.h"
@ -6,12 +6,15 @@
typedef enum { typedef enum {
RPKIND_KEY, RPKIND_KEY,
// NOTE(zaklaus): Special actions // NOTE(zaklaus): Special actions
RPKIND_SPAWN_CAR, RPKIND_SPAWN_CAR,
RPKIND_PLACE_ICE_RINK, RPKIND_PLACE_ICE_RINK,
RPKIND_PLACE_ERASE_CHANGES, RPKIND_PLACE_ERASE_CHANGES,
RPKIND_SPAWN_CIRCLING_DRIVER, RPKIND_SPAWN_CIRCLING_DRIVER,
RPKIND_SPAWN_ICEMAKER_ITEM,
RPKIND_SPAWN_CHEST,
RPKIND_SPAWN_BELT,
} replay_kind; } replay_kind;
typedef struct { typedef struct {
@ -42,17 +45,17 @@ static char replaybuf[sizeof(replay_record)*UINT16_MAX + 32];
void debug_replay_store(void) { void debug_replay_store(void) {
ZPL_ASSERT(replay_filename[0]); ZPL_ASSERT(replay_filename[0]);
if (!records) return; if (!records) return;
cw_pack_context pc = {0}; cw_pack_context pc = {0};
cw_pack_context_init(&pc, replaybuf, sizeof(replaybuf), 0); cw_pack_context_init(&pc, replaybuf, sizeof(replaybuf), 0);
cw_pack_unsigned(&pc, REPLAY_MAGIC); cw_pack_unsigned(&pc, REPLAY_MAGIC);
cw_pack_unsigned(&pc, REPLAY_VERSION); cw_pack_unsigned(&pc, REPLAY_VERSION);
cw_pack_array_size(&pc, (uint32_t)zpl_array_count(records)); cw_pack_array_size(&pc, (uint32_t)zpl_array_count(records));
for (int i = 0; i < zpl_array_count(records); i++) { for (int i = 0; i < zpl_array_count(records); i++) {
cw_pack_bin(&pc, &records[i], sizeof(replay_record)); cw_pack_bin(&pc, &records[i], sizeof(replay_record));
} }
zpl_file f = {0}; zpl_file f = {0};
zpl_file_create(&f, replay_filename); zpl_file_create(&f, replay_filename);
zpl_file_write(&f, replaybuf, pc.current - pc.start); zpl_file_write(&f, replaybuf, pc.current - pc.start);
@ -61,44 +64,44 @@ void debug_replay_store(void) {
void debug_replay_load(void) { void debug_replay_load(void) {
ZPL_ASSERT(replay_filename[0]); ZPL_ASSERT(replay_filename[0]);
zpl_file f = {0}; zpl_file f = {0};
zpl_file_error err = zpl_file_open(&f, replay_filename); zpl_file_error err = zpl_file_open(&f, replay_filename);
ZPL_ASSERT(err == ZPL_FILE_ERROR_NONE); ZPL_ASSERT(err == ZPL_FILE_ERROR_NONE);
size_t file_size = zpl_file_size(&f); size_t file_size = zpl_file_size(&f);
zpl_file_read(&f, replaybuf, file_size); zpl_file_read(&f, replaybuf, file_size);
zpl_file_close(&f); zpl_file_close(&f);
cw_unpack_context uc = {0}; cw_unpack_context uc = {0};
cw_unpack_context_init(&uc, replaybuf, (uint32_t)file_size, 0); cw_unpack_context_init(&uc, replaybuf, (uint32_t)file_size, 0);
cw_unpack_next(&uc); cw_unpack_next(&uc);
ZPL_ASSERT(uc.item.type == CWP_ITEM_POSITIVE_INTEGER && uc.item.as.u64 == REPLAY_MAGIC); ZPL_ASSERT(uc.item.type == CWP_ITEM_POSITIVE_INTEGER && uc.item.as.u64 == REPLAY_MAGIC);
cw_unpack_next(&uc); cw_unpack_next(&uc);
ZPL_ASSERT(uc.item.type == CWP_ITEM_POSITIVE_INTEGER); ZPL_ASSERT(uc.item.type == CWP_ITEM_POSITIVE_INTEGER);
uint64_t version = uc.item.as.u64; uint64_t version = uc.item.as.u64;
ZPL_ASSERT(version >= 2); ZPL_ASSERT(version >= 2);
cw_unpack_next(&uc); cw_unpack_next(&uc);
ZPL_ASSERT(uc.item.type == CWP_ITEM_ARRAY); ZPL_ASSERT(uc.item.type == CWP_ITEM_ARRAY);
size_t items = uc.item.as.array.size; size_t items = uc.item.as.array.size;
zpl_array_init_reserve(records, zpl_heap(), sizeof(replay_record)*items); zpl_array_init_reserve(records, zpl_heap(), sizeof(replay_record)*items);
for (size_t i = 0; i < items; i++) { for (size_t i = 0; i < items; i++) {
cw_unpack_next(&uc); cw_unpack_next(&uc);
ZPL_ASSERT(uc.item.type == CWP_ITEM_BIN); ZPL_ASSERT(uc.item.type == CWP_ITEM_BIN);
replay_record rec = {0}; replay_record rec = {0};
switch (version) { switch (version) {
case 2:{ case 2:{
debug_replay_load_record_v2(&rec, uc.item.as.bin.start); debug_replay_load_record_v2(&rec, uc.item.as.bin.start);
}break; }break;
default:{ default:{
zpl_memcopy(&rec, uc.item.as.bin.start, sizeof(replay_record)); zpl_memcopy(&rec, uc.item.as.bin.start, sizeof(replay_record));
}break; }break;
@ -109,10 +112,10 @@ void debug_replay_load(void) {
void debug_replay_start(void) { void debug_replay_start(void) {
is_recording = true; is_recording = true;
if (records) zpl_array_free(records); if (records) zpl_array_free(records);
zpl_array_init_reserve(records, zpl_heap(), UINT16_MAX); zpl_array_init_reserve(records, zpl_heap(), UINT16_MAX);
last_record_time = get_cached_time(); last_record_time = get_cached_time();
SetTargetFPS(60); SetTargetFPS(60);
} }
@ -127,17 +130,17 @@ void debug_replay_clear(void) {
void debug_replay_cleanup_ents(void) { void debug_replay_cleanup_ents(void) {
SetTargetFPS(0); SetTargetFPS(0);
if (!mime) return; if (!mime) return;
entity_despawn(mime); entity_despawn(mime);
mime = 0; mime = 0;
is_playing = false; is_playing = false;
camera_set_follow(plr); camera_set_follow(plr);
for (int i = 0; i < zpl_array_count(temp_actors); i++) { for (int i = 0; i < zpl_array_count(temp_actors); i++) {
entity_despawn(temp_actors[i]); entity_despawn(temp_actors[i]);
} }
zpl_array_free(temp_actors); zpl_array_free(temp_actors);
} }
@ -154,17 +157,17 @@ void debug_replay_run(void) {
record_pos = 0; record_pos = 0;
playback_time = get_cached_time(); playback_time = get_cached_time();
zpl_array_init(temp_actors, zpl_heap()); zpl_array_init(temp_actors, zpl_heap());
plr = camera_get().ent_id; plr = camera_get().ent_id;
Position const *p1 = ecs_get(world_ecs(), plr, Position); Position const *p1 = ecs_get(world_ecs(), plr, Position);
mime = entity_spawn(EKIND_MACRO_BOT); mime = entity_spawn(EKIND_MACRO_BOT);
Position *pos = ecs_get_mut(world_ecs(), mime, Position); Position *pos = ecs_get_mut(world_ecs(), mime, Position);
*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}); ecs_set(world_ecs(), mime, Inventory, {0});
camera_set_follow(mime); camera_set_follow(mime);
SetTargetFPS(60); SetTargetFPS(60);
} }
@ -179,10 +182,10 @@ void ActSpawnBelt(void);
void debug_replay_update(void) { void debug_replay_update(void) {
if (!is_playing) return; if (!is_playing) return;
if (playback_time >= get_cached_time()) return; if (playback_time >= get_cached_time()) return;
replay_record *r = &records[record_pos]; replay_record *r = &records[record_pos];
playback_time = get_cached_time() + r->delay; playback_time = get_cached_time() + r->delay;
switch (r->kind) { switch (r->kind) {
case RPKIND_KEY: { case RPKIND_KEY: {
Input *i = ecs_get_mut(world_ecs(), mime, Input); Input *i = ecs_get_mut(world_ecs(), mime, Input);
@ -206,11 +209,11 @@ void debug_replay_update(void) {
}break; }break;
case RPKIND_SPAWN_CAR: { case RPKIND_SPAWN_CAR: {
ecs_entity_t e = vehicle_spawn(EVEH_CAR); ecs_entity_t e = vehicle_spawn(EVEH_CAR);
Position const *origin = ecs_get(world_ecs(), mime, Position); Position const *origin = ecs_get(world_ecs(), mime, Position);
Position *dest = ecs_get_mut(world_ecs(), e, Position); Position *dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin; *dest = *origin;
zpl_array_append(temp_actors, e); zpl_array_append(temp_actors, e);
}break; }break;
case RPKIND_PLACE_ICE_RINK: { case RPKIND_PLACE_ICE_RINK: {
@ -222,13 +225,22 @@ void debug_replay_update(void) {
case RPKIND_PLACE_ERASE_CHANGES:{ case RPKIND_PLACE_ERASE_CHANGES:{
ActEraseWorldChanges(); ActEraseWorldChanges();
}break; }break;
case RPKIND_SPAWN_ICEMAKER_ITEM:{
ActSpawnCoal();
}break;
case RPKIND_SPAWN_CHEST:{
ActSpawnChest();
}break;
case RPKIND_SPAWN_BELT:{
ActSpawnBelt();
}break;
default: { default: {
ZPL_PANIC("unreachable"); ZPL_PANIC("unreachable");
}break; }break;
} }
record_pos += 1; record_pos += 1;
// NOTE(zaklaus): remove our dummy art exhibist // NOTE(zaklaus): remove our dummy art exhibist
if (mime && record_pos == zpl_array_count(records)) { if (mime && record_pos == zpl_array_count(records)) {
debug_replay_cleanup_ents(); debug_replay_cleanup_ents();
@ -238,13 +250,13 @@ void debug_replay_update(void) {
void debug_replay_record_keystate(pkt_send_keystate state) { void debug_replay_record_keystate(pkt_send_keystate state) {
if (!is_recording) return; if (!is_recording) return;
double record_time = get_cached_time(); double record_time = get_cached_time();
replay_record rec = { replay_record rec = {
.kind = RPKIND_KEY, .kind = RPKIND_KEY,
.pkt = state, .pkt = state,
.delay = (record_time - last_record_time), .delay = (record_time - last_record_time),
}; };
zpl_array_append(records, rec); zpl_array_append(records, rec);
last_record_time = get_cached_time(); last_record_time = get_cached_time();
} }
@ -253,12 +265,12 @@ void debug_replay_special_action(replay_kind kind) {
ZPL_ASSERT(kind != RPKIND_KEY); ZPL_ASSERT(kind != RPKIND_KEY);
if (!is_recording || is_playing) return; if (!is_recording || is_playing) return;
double record_time = get_cached_time(); double record_time = get_cached_time();
replay_record rec = { replay_record rec = {
.kind = kind, .kind = kind,
.delay = (record_time - last_record_time), .delay = (record_time - last_record_time),
}; };
zpl_array_append(records, rec); zpl_array_append(records, rec);
last_record_time = get_cached_time(); last_record_time = get_cached_time();
} }

View File

@ -1,5 +1,5 @@
#include "dev/debug_ui.h" #include "debug/debug_ui.h"
#include "dev/debug_draw.h" #include "debug/debug_draw.h"
#include "raylib.h" #include "raylib.h"
#include "models/prefabs/vehicle.h" #include "models/prefabs/vehicle.h"
#include "core/camera.h" #include "core/camera.h"
@ -9,10 +9,6 @@
#include "models/components.h" #include "models/components.h"
ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0)
#include "raylib-nuklear.h"
ZPL_DIAGNOSTIC_POP
typedef enum { typedef enum {
DITEM_RAW, DITEM_RAW,
DITEM_GAP, DITEM_GAP,
@ -20,9 +16,7 @@ typedef enum {
DITEM_BUTTON, DITEM_BUTTON,
DITEM_SLIDER, DITEM_SLIDER,
DITEM_LIST, DITEM_LIST,
DITEM_TOOL,
DITEM_COND, DITEM_COND,
DITEM_END, DITEM_END,
DITEM_FORCE_UINT8 = UINT8_MAX DITEM_FORCE_UINT8 = UINT8_MAX
@ -47,8 +41,6 @@ static uint8_t is_debug_open = 1;
static uint8_t is_handle_ctrl_held; static uint8_t is_handle_ctrl_held;
static float debug_xpos = DBG_START_XPOS; static float debug_xpos = DBG_START_XPOS;
static float debug_ypos = DBG_START_YPOS; static float debug_ypos = DBG_START_YPOS;
static zpl_u16 sel_item_id = 0;
static struct nk_context *dev_ui = 0;
typedef enum { typedef enum {
L_NONE = 0, L_NONE = 0,
@ -79,11 +71,6 @@ typedef struct debug_item {
void (*on_change)(float); void (*on_change)(float);
} slider; } slider;
struct {
uint8_t is_open;
void (*on_draw)(void);
} tool;
void (*on_click)(void); void (*on_click)(void);
uint8_t (*on_success)(void); uint8_t (*on_success)(void);
@ -95,13 +82,10 @@ typedef struct debug_item {
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);
#include "dev/debug_replay.c" #include "debug/debug_replay.c"
#include "gui/ui_skin.c" #include "debug/debug_ui_actions.c"
#include "debug/debug_ui_widgets.c"
#include "dev/debug_ui_actions.c"
#include "dev/debug_ui_widgets.c"
#include "dev/debug_ui_tools.c"
static debug_item items[] = { static debug_item items[] = {
{ {
@ -149,24 +133,17 @@ static debug_item items[] = {
.list = { .list = {
.is_collapsed = true, .is_collapsed = true,
.items = (debug_item[]) { .items = (debug_item[]) {
{ { .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar },
.kind = DITEM_LIST,
.name = "spawn item",
.list = {
.items = (debug_item[]) {
{ .kind = DITEM_TEXT, .name = "selected", .proc = DrawSelectedSpawnItem },
{ .kind = DITEM_BUTTON, .name = "Previous", .on_click = ActSpawnItemPrev },
{ .kind = DITEM_BUTTON, .name = "Next", .on_click = ActSpawnItemNext },
{ .kind = DITEM_BUTTON, .name = "Spawn <", .on_click = ActSpawnSelItem },
{ .kind = DITEM_END },
},
.is_collapsed = false
}
},
{ .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar },
{ .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink }, { .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink },
{ .kind = DITEM_BUTTON, .name = "erase world changes", .on_click = ActEraseWorldChanges }, { .kind = DITEM_BUTTON, .name = "erase world changes", .on_click = ActEraseWorldChanges },
{ .kind = DITEM_BUTTON, .name = "spawn circling driver", .on_click = ActSpawnCirclingDriver }, { .kind = DITEM_BUTTON, .name = "spawn circling driver", .on_click = ActSpawnCirclingDriver },
{ .kind = DITEM_BUTTON, .name = "spawn coal lump", .on_click = ActSpawnCoal },
{ .kind = DITEM_BUTTON, .name = "spawn chest", .on_click = ActSpawnChest },
{ .kind = DITEM_BUTTON, .name = "spawn belt", .on_click = ActSpawnBelt },
{ .kind = DITEM_BUTTON, .name = "spawn furnace", .on_click = ActSpawnFurnace },
{ .kind = DITEM_BUTTON, .name = "spawn big tree", .on_click = ActSpawnBigTree },
{ .kind = DITEM_BUTTON, .name = "spawn demo blueprint", .on_click = ActSpawnDemoHouseItem },
{ .kind = DITEM_BUTTON, .name = "spawn random durability icemaker", .on_click = ActSpawnDurabilityTest },
{ {
.kind = DITEM_LIST, .kind = DITEM_LIST,
.name = "demo npcs", .name = "demo npcs",
@ -255,27 +232,12 @@ static debug_item items[] = {
{ .kind = DITEM_RAW, .val = PROF_RENDER, .proc = DrawProfilerDelta }, { .kind = DITEM_RAW, .val = PROF_RENDER, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta }, { .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta }, { .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_INTEGRATE_POS, .proc = DrawProfilerDelta }, { .kind = DITEM_RAW, .val = PROF_INTEGRATE_POS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_PHYS_BLOCK_COLS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_PHYS_BODY_COLS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_RENDER_PUSH_AND_SORT_ENTRIES, .proc = DrawProfilerDelta },
{ .kind = DITEM_END }, { .kind = DITEM_END },
}, },
.is_collapsed = 1 .is_collapsed = 1
} }
}, },
{
.kind = DITEM_LIST,
.name = "tools",
.list = {
.items = (debug_item[]) {
{ .kind = DITEM_TOOL, .name = "asset inspector", .tool = { .is_open = 0, .on_draw = ToolAssetInspector } },
{ .kind = DITEM_TOOL, .name = "entity inspector", .tool = { .is_open = 0, .on_draw = ToolEntityInspector } },
{ .kind = DITEM_END },
},
.is_collapsed = 0
}
},
#if !defined(PLATFORM_WEB) #if !defined(PLATFORM_WEB)
{ {
.kind = DITEM_BUTTON, .kind = DITEM_BUTTON,
@ -378,25 +340,6 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
ypos += DBG_FONT_SPACING; ypos += DBG_FONT_SPACING;
}break; }break;
case DITEM_TOOL: {
char const *text = TextFormat("> %s", it->name);
if (it->name_width == 0) {
it->name_width = (float)UIMeasureText(text, DBG_FONT_SIZE);
}
Color color = RAYWHITE;
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color)) {
it->tool.is_open ^= 1;
}
debug_draw_result res = DrawColoredText(xpos, ypos, text, color);
ypos = res.y;
if (it->tool.is_open) {
if (is_shadow_rendered) break;
it->tool.on_draw();
}
} break;
default: { default: {
}break; }break;
@ -410,19 +353,6 @@ void debug_draw(void) {
// NOTE(zaklaus): Flush old debug samples // NOTE(zaklaus): Flush old debug samples
debug_draw_flush(); debug_draw_flush();
set_style(dev_ui, THEME_RED);
static zpl_u8 first_run=0;
if (!first_run) {
first_run = 1;
ActSpawnItemNext();
// Initialize Nuklear ctx
dev_ui = InitNuklear(10);
}
UpdateNuklear(dev_ui);
float xpos = debug_xpos; float xpos = debug_xpos;
float ypos = debug_ypos; float ypos = debug_ypos;
@ -467,8 +397,6 @@ void debug_draw(void) {
debug_draw_list(items, xpos+DBG_SHADOW_OFFSET_XPOS, ypos+DBG_SHADOW_OFFSET_YPOS, 1); // NOTE(zaklaus): draw shadow debug_draw_list(items, xpos+DBG_SHADOW_OFFSET_XPOS, ypos+DBG_SHADOW_OFFSET_YPOS, 1); // NOTE(zaklaus): draw shadow
debug_draw_list(items, xpos, ypos, 0); debug_draw_list(items, xpos, ypos, 0);
} }
DrawNuklear(dev_ui);
} }
debug_area_status check_mouse_area(float xpos, float ypos, float w, float h) { debug_area_status check_mouse_area(float xpos, float ypos, float w, float h) {

View File

@ -1,10 +1,8 @@
#include "dev/debug_ui.h" #include "debug/debug_ui.h"
#include "world/blocks.h" #include "world/blocks.h"
#include "models/items.h" #include "models/items.h"
#include "net/network.h" #include "net/network.h"
#include "models/entity.h"
void void
ActExitGame(void) { ActExitGame(void) {
game_request_close(); game_request_close();
@ -24,34 +22,89 @@ ActSpawnCar(void) {
} }
void void
ActSpawnItemPrev(void) { ActSpawnCoal(void) {
while (true) { ecs_entity_t e = item_spawn(ASSET_COAL, 32);
--sel_item_id;
item_id id = item_find_no_proxy(sel_item_id);
if (sel_item_id > 0 && id != ASSET_INVALID && (item_get_usage(id) != UKIND_PROXY)) {
break;
}
}
}
void
ActSpawnItemNext(void) {
while (true) {
++sel_item_id;
item_id id = item_find_no_proxy(sel_item_id);
if (sel_item_id > 0 && id != ASSET_INVALID && (item_get_usage(id) != UKIND_PROXY)) {
break;
}
}
}
void
ActSpawnSelItem(void) {
ecs_entity_t e = item_spawn(sel_item_id, 32);
ecs_entity_t plr = camera_get().ent_id; ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position); Position const* origin = ecs_get(world_ecs(), plr, Position);
entity_set_position(e, origin->x, origin->y); Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
debug_replay_special_action(RPKIND_SPAWN_ICEMAKER_ITEM);
}
void
ActSpawnChest(void) {
ecs_entity_t e = item_spawn(ASSET_CHEST, 32);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
debug_replay_special_action(RPKIND_SPAWN_CHEST);
}
void
ActSpawnBelt(void) {
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);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
debug_replay_special_action(RPKIND_SPAWN_BELT);
}
void
ActSpawnDurabilityTest(void) {
ecs_entity_t e = item_spawn(ASSET_COAL, 1);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
Item *it = ecs_get_mut(world_ecs(), e, Item);
it->durability = (float)(rand() % 100) / 100.0f;
}
void
ActSpawnFurnace(void) {
ecs_entity_t e = item_spawn(ASSET_FURNACE, 32);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
}
void
ActSpawnBigTree(void) {
ecs_entity_t e = item_spawn(ASSET_BIG_TREE, 32);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
}
void
ActSpawnDemoHouseItem(void) {
ecs_entity_t e = item_spawn(ASSET_BLUEPRINT, 1);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position);
*dest = *origin;
entity_set_position(e, dest->x, dest->y);
} }
void void
@ -232,7 +285,8 @@ ActSpawnDemoNPCs(void) {
if (zpl_array_count(demo_npcs) >= 100000) return; if (zpl_array_count(demo_npcs) >= 100000) return;
for (uint32_t i = 0; i < 1000; i++) { for (uint32_t i = 0; i < 1000; i++) {
uint64_t e = entity_spawn_id(ASSET_CREATURE); uint64_t e = entity_spawn(EKIND_DEMO_NPC);
ecs_add(world_ecs(), e, DemoNPC);
Position *pos = ecs_get_mut(world_ecs(), e, Position); Position *pos = ecs_get_mut(world_ecs(), e, Position);
pos->x=(float)(rand() % world_dim()); pos->x=(float)(rand() % world_dim());
pos->y=(float)(rand() % world_dim()); pos->y=(float)(rand() % world_dim());

View File

@ -1,4 +1,4 @@
#include "dev/debug_ui.h" #include "debug/debug_ui.h"
#include "raylib.h" #include "raylib.h"
#include "platform/platform.h" #include "platform/platform.h"
#include "net/network.h" #include "net/network.h"
@ -119,11 +119,6 @@ DrawDemoNPCCount(debug_item *it, float xpos, float ypos) {
return DrawFormattedText(xpos, ypos, TextFormat("%d", demo_npcs ? zpl_array_count(demo_npcs) : 0)); return DrawFormattedText(xpos, ypos, TextFormat("%d", demo_npcs ? zpl_array_count(demo_npcs) : 0));
} }
static inline debug_draw_result
DrawSelectedSpawnItem(debug_item *it, float xpos, float ypos) {
(void)it;
return DrawFormattedText(xpos, ypos, TextFormat("%s", asset_names[sel_item_id]));
}
// NOTE(zaklaus): world simulation // NOTE(zaklaus): world simulation
static inline debug_draw_result static inline debug_draw_result

View File

@ -1,143 +0,0 @@
// debug tools written with Nuklear UI
#include "models/assets.h"
#include "world/blocks.h"
#include "models/items.h"
extern void tooltip_show_cursor(const char* name);
extern const char *tooltip_find_desc_contents(const char *name);
void ToolAssetInspector(void) {
if (nk_begin(dev_ui, "Asset Inspector", nk_rect(400, 100, 240, 800),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_TITLE))
{
for (int i = 0; i < MAX_ASSETS; i++) {
uint16_t idx = assets_find(i);
if (idx != ASSET_INVALID && nk_tree_push_id(dev_ui, NK_TREE_TAB, asset_names[i], NK_MINIMIZED, i)) {
{
// draw kind
const char *asset_kind_name = assets_get_kind_name(idx);
nk_labelf(dev_ui, NK_TEXT_LEFT, "kind: %s", asset_kind_name);
nk_labelf(dev_ui, NK_TEXT_LEFT, "spawnable entity: %s", entity_spawn_provided(i) ? "true" : "false");
if (nk_button_label(dev_ui, "show tooltip")) {
tooltip_show_cursor(asset_names[i]);
}
if (nk_button_label(dev_ui, "spawn at me")) {
uint64_t e = entity_spawn_id(i);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
entity_set_position(e, origin->x, origin->y);
}
// draw help text
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "description", NK_MINIMIZED, i)) {
{
const char *desc = tooltip_find_desc_contents(asset_names[i]);
if (desc) {
nk_layout_row_dynamic(dev_ui, 0, 1);
nk_label_wrap(dev_ui, desc);
}
}
nk_tree_pop(dev_ui);
}
// draw block
block_id blk_id = blocks_find(i);
if (blk_id != 0xF) {
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "block", NK_MINIMIZED, i)) {
{
nk_labelf(dev_ui, NK_TEXT_LEFT, "symbol: %s", zpl_bprintf("%c", blocks_get_symbol(blk_id)));
nk_labelf(dev_ui, NK_TEXT_LEFT, "flags: %u", blocks_get_flags(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "drag: %f", blocks_get_drag(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "friction: %f", blocks_get_friction(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "bounce: %f", blocks_get_bounce(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "velx: %f", blocks_get_velx(blk_id));
nk_labelf(dev_ui, NK_TEXT_LEFT, "vely: %f", blocks_get_vely(blk_id));
}
nk_tree_pop(dev_ui);
}
}
// draw item
item_id it_id = item_find_no_proxy(i);
if (it_id != ASSET_INVALID) {
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "item", NK_MINIMIZED, i)) {
{
item_desc it = item_get_desc(it_id);
if (nk_button_label(dev_ui, "spawn")) {
ecs_entity_t e = item_spawn(i, it.max_quantity);
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
entity_set_position(e, origin->x, origin->y);
}
nk_labelf(dev_ui, NK_TEXT_LEFT, "usage: %d", it.usage);
nk_labelf(dev_ui, NK_TEXT_LEFT, "attachment: %d", it.attachment);
nk_labelf(dev_ui, NK_TEXT_LEFT, "max quantity: %d", it.max_quantity);
nk_labelf(dev_ui, NK_TEXT_LEFT, "has storage: %s", it.has_storage ? "true" : "false");
// todo: draw item-specific data
}
nk_tree_pop(dev_ui);
}
}
}
nk_tree_pop(dev_ui);
}
}
nk_end(dev_ui);
}
}
void ToolEntityInspector(void) {
if (nk_begin(dev_ui, "Entity Inspector", nk_rect(660, 100, 240, 800),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_TITLE))
{
static ecs_query_t *q = 0;
if (!q) {
q = ecs_query(world_ecs(), {
.filter.terms = {
{ .id = ecs_id(Position) },
{ .id = ecs_id(Classify), .inout = EcsIn }
}
});
}
ecs_iter_t it = ecs_query_iter(world_ecs(), q);
while (ecs_query_next(&it)) {
Position *p = ecs_field(&it, Position, 1);
const Classify *c = ecs_field(&it, Classify, 2);
for (int i = 0; i < it.count; i++) {
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, zpl_bprintf("%lld [%s]", it.entities[i], class_names[c[i].id]), NK_MINIMIZED, (int)it.entities[i])) {
{
nk_label(dev_ui, "position:", NK_TEXT_LEFT);
nk_property_float(dev_ui, "#x:", ZPL_F32_MIN, &p[i].x, ZPL_F32_MAX, 0.1f, 0.2f);
nk_property_float(dev_ui, "#y:", ZPL_F32_MIN, &p[i].y, ZPL_F32_MAX, 0.1f, 0.2f);
if (nk_button_label(dev_ui, "teleport to")) {
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), it.entities[i], Position);
entity_set_position(plr, origin->x, origin->y);
}
if (nk_button_label(dev_ui, "teleport here")) {
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
entity_set_position(it.entities[i], origin->x, origin->y);
}
}
nk_tree_pop(dev_ui);
}
}
}
nk_end(dev_ui);
}
}

View File

@ -7,9 +7,11 @@ Texture2D texgen_build_anim_fallback(asset_id id, int64_t counter) {
(void)counter; (void)counter;
switch (id) { switch (id) {
case ASSET_WATER: { case ASSET_WATER: {
return LoadTexEco(zpl_bprintf("%s%d", "water", counter%3)); Image img = LoadImageEco("water");
ImageColorBrightness(&img, zpl_abs((counter % 64 - 32)*2));
return Image2TexEco(img);
}break; }break;
default: return GenColorEco(PINK); break; default: return GenColorEco(PINK); break;
} }
} }
@ -19,18 +21,12 @@ Texture2D texgen_build_sprite_fallback(asset_id id) {
case ASSET_BLANK: return GenColorEco(WHITE); break; case ASSET_BLANK: return GenColorEco(WHITE); break;
case ASSET_BUILDMODE_HIGHLIGHT: return GenColorEco(WHITE); break; case ASSET_BUILDMODE_HIGHLIGHT: return GenColorEco(WHITE); break;
case ASSET_BLOCK_FRAME: return GenFrameRect(); break; case ASSET_BLOCK_FRAME: return GenFrameRect(); break;
case ASSET_BIG_TREE: return LoadTexEco("bigtree"); break;
// NOTE(zaklaus): items // NOTE(zaklaus): items
case ASSET_COAL: return LoadTexEco("coal"); case ASSET_COAL: return LoadTexEco("coal");
case ASSET_IRON_ORE: return LoadTexEco("iron_ore"); case ASSET_BLUEPRINT: return LoadTexEco("blueprint");
case ASSET_IRON_INGOT: return LoadTexEco("iron_ingot");
case ASSET_IRON_PLATES: return LoadTexEco("iron_plate");
case ASSET_SCREWS: return LoadTexEco("screws");
case ASSET_LOG: return LoadTexEco("log");
case ASSET_PLANK: return LoadTexEco("plank");
case ASSET_CREATURE: return GenColorEco(YELLOW);
case ASSET_CREATURE_FOOD: return GenColorEco(GREEN);
// NOTE(zaklaus): blocks // NOTE(zaklaus): blocks
case ASSET_FENCE: return LoadTexEco("fence"); case ASSET_FENCE: return LoadTexEco("fence");
case ASSET_GROUND: return LoadTexEco("grass"); case ASSET_GROUND: return LoadTexEco("grass");
@ -40,29 +36,19 @@ Texture2D texgen_build_sprite_fallback(asset_id id) {
case ASSET_HILL: return LoadTexEco("rock"); case ASSET_HILL: return LoadTexEco("rock");
case ASSET_LAVA: return LoadTexEco("lava"); case ASSET_LAVA: return LoadTexEco("lava");
case ASSET_WOOD: return LoadTexEco("wood"); case ASSET_WOOD: return LoadTexEco("wood");
case ASSET_TREE: return LoadTexEco("bigtree"); case ASSET_TREE: return LoadTexEco("tree");
case ASSET_TEST_TALL: return LoadTexEco("test-tall");
// case ASSET_WATER: return LoadTexEco("water"); // case ASSET_WATER: return LoadTexEco("water");
case ASSET_BELT: case ASSET_BELT:
case ASSET_BELT_RIGHT: return LoadTexEco("belt_right"); case ASSET_BELT_RIGHT: return LoadTexEco("belt_right");
case ASSET_BELT_LEFT: return LoadTexEco("belt_left"); case ASSET_BELT_LEFT: return LoadTexEco("belt_left");
case ASSET_BELT_UP: return LoadTexEco("belt_up"); case ASSET_BELT_UP: return LoadTexEco("belt_up");
case ASSET_BELT_DOWN: return LoadTexEco("belt_down"); case ASSET_BELT_DOWN: return LoadTexEco("belt_down");
// NOTE(zaklaus): devices // NOTE(zaklaus): devices
case ASSET_CHEST: return LoadTexEco("chest"); case ASSET_CHEST: return LoadTexEco("chest");
case ASSET_FURNACE: return LoadTexEco("furnace"); case ASSET_FURNACE: return LoadTexEco("furnace-export");
case ASSET_CRAFTBENCH: return LoadTexEco("craftbench");
case ASSET_SPLITTER: return LoadTexEco("item_splitter"); default: return GenColorEco(PINK); break;
case ASSET_ASSEMBLER: return LoadTexEco("assembler");
default: break;
} }
if (id > ASSET_BLUEPRINT_BEGIN && id < ASSET_BLUEPRINT_END) {
return LoadTexEco("blueprint");
}
return GenColorEco(PINK);
} }

View File

@ -27,27 +27,27 @@ void buildmode_draw(void) {
platform_get_block_realpos(&mx, &my); platform_get_block_realpos(&mx, &my);
cam.x = (double)mx; cam.x = (double)mx;
cam.y = (double)my; cam.y = (double)my;
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BLOCK_FRAME, WHITE); renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BLOCK_FRAME, WHITE);
// NOTE(zaklaus): Check distance // NOTE(zaklaus): Check distance
double dx = old_cam.x - cam.x; double dx = old_cam.x - cam.x;
double dy = old_cam.y - cam.y; double dy = old_cam.y - cam.y;
double dsq = (dx*dx + dy*dy); double dsq = (dx*dx + dy*dy);
bool is_outside_range = (dsq > zpl_square(WORLD_BLOCK_SIZE*14)); bool is_outside_range = (dsq > zpl_square(WORLD_BLOCK_SIZE*14));
if (build_submit_placements) { if (build_submit_placements) {
build_submit_placements = false; build_submit_placements = false;
buildmode_clear_buffers(); buildmode_clear_buffers();
} }
if (input_is_pressed(IN_TOGGLE_DEMOLITION)){ if (IsKeyPressed(KEY_B)){
build_is_deletion_mode = !build_is_deletion_mode; build_is_deletion_mode = !build_is_deletion_mode;
} }
Item *item = &e->items[e->selected_item]; Item *item = &e->items[e->selected_item];
if (e->has_items && !e->inside_vehicle && (build_is_deletion_mode || (item->quantity > 0 && !is_outside_range))) { if (e->has_items && !e->inside_vehicle && item->quantity > 0 && (!is_outside_range || build_is_deletion_mode)) {
item_usage usage = 0; item_usage usage = 0;
uint16_t item_id = 0; uint16_t item_id = 0;
if (!build_is_deletion_mode){ if (!build_is_deletion_mode){
@ -60,21 +60,20 @@ void buildmode_draw(void) {
build_num_placements = 0; build_num_placements = 0;
buildmode_clear_buffers(); buildmode_clear_buffers();
} }
uint32_t qty = BUILD_MAX_PLACEMENTS; uint32_t qty = BUILD_MAX_PLACEMENTS;
bool directional = false; bool directional = false;
if (!build_is_deletion_mode){ if (!build_is_deletion_mode){
directional = item_get_place_directional(item_id); directional = item_get_place_directional(item_id);
qty = item->quantity; qty = item->quantity;
} }
world_view_block_lookup l = world_view_block_from_realpos(game_world_view_get_active(), (float)cam.x, (float)cam.y); world_block_lookup l = world_block_from_realpos((float)cam.x, (float)cam.y);
if (build_is_deletion_mode && !l.is_outer){ if (build_is_deletion_mode && !l.is_outer){
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(RED, 0.4f));
goto build_skip_placements; goto build_skip_placements;
} }
if (build_is_in_draw_mode) { if (build_is_in_draw_mode) {
for (size_t i = 0; i < BUILD_MAX_PLACEMENTS; i++) { for (size_t i = 0; i < BUILD_MAX_PLACEMENTS; i++) {
item_placement *it = &build_placements[i]; item_placement *it = &build_placements[i];
@ -90,7 +89,7 @@ void buildmode_draw(void) {
float sy = zpl_sign0(p2y-p1y); float sy = zpl_sign0(p2y-p1y);
float sxx = zpl_sign0(p3x-p1x); float sxx = zpl_sign0(p3x-p1x);
float syy = zpl_sign0(p3y-p1y); float syy = zpl_sign0(p3y-p1y);
if (sx != sxx || sy != syy) break; if (sx != sxx || sy != syy) break;
} }
it->x = (float)cam.x; it->x = (float)cam.x;
@ -103,35 +102,31 @@ void buildmode_draw(void) {
} }
} }
} }
if (!is_outside_range) { if (!is_outside_range)
if (build_is_deletion_mode) renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : WHITE, 0.2f));
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(RED, 0.2f));
else
renderer_draw_single((float)cam.x, (float)cam.y, item->kind, ColorAlpha(WHITE, 0.2f));
}
build_skip_placements: build_skip_placements:
build_num_placements = zpl_min(build_num_placements, qty); build_num_placements = zpl_min(build_num_placements, qty);
} }
} }
for (size_t i = 0; i < build_num_placements; i++) { for (size_t i = 0; i < build_num_placements; i++) {
item_placement *it = &build_placements[i]; item_placement *it = &build_placements[i];
renderer_draw_single(it->x, it->y, !build_is_deletion_mode ? item->kind : ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : RAYWHITE, 0.6f)); renderer_draw_single(it->x, it->y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : WHITE, 0.4f));
} }
if (build_is_in_draw_mode) { if (build_is_in_draw_mode) {
if (IsKeyPressed(KEY_SPACE)) { if (IsKeyPressed(KEY_SPACE)) {
build_is_in_draw_mode = false; build_is_in_draw_mode = false;
buildmode_clear_buffers(); buildmode_clear_buffers();
} }
if (IsMouseButtonReleased(MOUSE_RIGHT_BUTTON)) { if (IsMouseButtonReleased(MOUSE_RIGHT_BUTTON)) {
build_submit_placements = true; build_submit_placements = true;
build_is_in_draw_mode = false; build_is_in_draw_mode = false;
} }
} }
} }

View File

@ -1,19 +1,16 @@
#include "models/crafting.h"
typedef struct { typedef struct {
uint8_t selected_item; uint8_t selected_item;
bool drop_item; bool drop_item;
bool item_is_held; bool item_is_held;
uint8_t held_item_idx; uint8_t held_item_idx;
Item held_item; Item held_item;
bool is_inside; bool is_inside;
bool storage_action; bool storage_action;
bool swap; bool swap;
uint8_t swap_from; uint8_t swap_from;
uint8_t swap_to; uint8_t swap_to;
uint16_t craft_item;
} inv_keystate; } inv_keystate;
static inv_keystate player_inv = {0}; static inv_keystate player_inv = {0};
@ -24,147 +21,31 @@ bool inv_is_inside = false;
bool inv_is_storage_action = false; bool inv_is_storage_action = false;
bool inv_swap_storage = false; bool inv_swap_storage = false;
// TODO(zaklaus):
// TODO(zaklaus): MOVE TO COMMON UI MODULE
// TODO(zaklaus):
typedef struct {
float x, y;
} inv_draw_result;
static inline
int UIMeasureText(const char *text, int fontSize) {
Vector2 vec = { 0.0f, 0.0f };
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0) {
int defaultFontSize = 10; // Default Font chars height in pixel
int new_spacing = fontSize/defaultFontSize;
vec = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)new_spacing);
}
return (int)vec.x;
}
static inline
void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color) {
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0) {
Vector2 position = { (float)posX , (float)posY };
int defaultFontSize = 22; // Default Font chars height in pixel
int new_spacing = fontSize/defaultFontSize;
DrawTextEx(GetFontDefault(), text, position, (float)fontSize , (float)new_spacing , color);
}
}
static inline inv_draw_result
DrawColoredText(float xpos, float ypos, char const *text, Color color) {
ZPL_ASSERT(text);
UIDrawText(text, xpos, ypos, 22, color);
char const *p = text;
uint8_t newlines = 1;
do {
if (*p == '\n')
++newlines;
} while (*p++ != 0);
return (inv_draw_result){.x = xpos + UIMeasureText(text, 22), .y = ypos + 22*newlines};
}
static inline
inv_draw_result inventory_draw_crafting_btn(float xpos, float ypos, const char *name, uint16_t id, Color color) {
float name_width=0.0f;
char const *text = TextFormat("> %s", name);
name_width = (float)UIMeasureText(text, 22);
Color new_color = color;
if (is_btn_pressed(xpos, ypos, name_width, 22, &new_color)) {
inv_is_inside = true;
player_inv.craft_item = id;
}
if (check_mouse_area(xpos, ypos, name_width, 22) != DAREA_OUTSIDE) {
Vector2 mpos = GetMousePosition();
recipe rp = craft_get_recipe_data(craft_get_recipe_id_from_product(id));
if (nk_begin(game_ui , name, nk_rect(mpos.x+15, mpos.y+15, name_width+5, 1200),
NK_WINDOW_BORDER | NK_WINDOW_NO_INPUT | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_DYNAMIC)) {
if (nk_tree_push_id(game_ui, NK_TREE_NODE, "Overview", NK_MAXIMIZED, id)) {
{
tooltip_draw_contents(tooltip_find_desc(name));
}
nk_tree_pop(game_ui);
}
if (nk_tree_push_id(game_ui, NK_TREE_NODE, "Reagents", NK_MAXIMIZED, id)) {
for (asset_id i = 0; rp.reagents[i].id; i++) {
nk_label(game_ui, asset_names[rp.reagents[i].id], NK_TEXT_LEFT);
}
nk_tree_pop(game_ui);
}
nk_end(game_ui);
}
}
Color _c_compare_lol = BLACK;
if (!zpl_memcompare(&color, &_c_compare_lol, sizeof(Color))) {
new_color = BLACK;
}
inv_draw_result res = DrawColoredText(xpos, ypos, text, new_color);
ypos = res.y;
return res;
}
static inline
bool inventory_draw_crafting_list(entity_view *e, float xpos, float ypos) {
float start_xpos = xpos;
float start_ypos = ypos;
for (uint16_t i = 0; e->craftables[i]; ++i) {
asset_id id = e->craftables[i];
inventory_draw_crafting_btn(start_xpos+1, ypos+1, asset_names[id], id, BLACK);
inv_draw_result entry = inventory_draw_crafting_btn(start_xpos, ypos, asset_names[id], id, RAYWHITE);
ypos = entry.y;
xpos = zpl_max(xpos, entry.x);
}
return check_mouse_area(start_xpos, start_ypos, xpos-start_xpos, ypos-start_ypos) != DAREA_OUTSIDE;
}
void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){ void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
if (!e->has_items && is_player) if (!e->has_items && is_player)
return; return;
if (!e->has_storage_items && !is_player) if (!e->has_storage_items && !is_player)
return; return;
float x = sx; float x = sx;
float y = sy; float y = sy;
const int32_t grid_size = (is_player) ? (64*3) : (64*4); const int32_t grid_size = (is_player) ? (64*3) : (64*4);
const int32_t inv_size = (is_player) ? ITEMS_INVENTORY_SIZE : ITEMS_CONTAINER_SIZE; const int32_t inv_size = (is_player) ? ITEMS_INVENTORY_SIZE : ITEMS_CONTAINER_SIZE;
const int32_t inv_cols = (is_player) ? 3 : 4; const int32_t inv_cols = (is_player) ? 3 : 4;
inv_keystate *inv = (!is_player) ? &storage_inv : &player_inv; inv_keystate *inv = (!is_player) ? &storage_inv : &player_inv;
inv_keystate *inv2 = (is_player) ? &storage_inv : &player_inv; inv_keystate *inv2 = (is_player) ? &storage_inv : &player_inv;
bool inside_craft = !is_player && inventory_draw_crafting_list(e, screenWidth/2.0f - 684, screenHeight/2.0f - 128);
inv->is_inside = check_mouse_area(sx, sy, (float)grid_size, (float)grid_size) != DAREA_OUTSIDE; inv->is_inside = check_mouse_area(sx, sy, (float)grid_size, (float)grid_size) != DAREA_OUTSIDE;
inv_is_inside |= inv->is_inside || inside_craft; inv_is_inside |= inv->is_inside;
for (int32_t i = 0; i < inv_size; i += 1) { for (int32_t i = 0; i < inv_size; i += 1) {
{ {
debug_area_status area = check_mouse_area(x, y, 64, 64); debug_area_status area = check_mouse_area(x, y, 64, 64);
Color color = RAYWHITE; Color color = RAYWHITE;
Item *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) { if (area == DAREA_HOVER) {
color = YELLOW; color = YELLOW;
} else if (area == DAREA_PRESS && inv2->item_is_held){ } else if (area == DAREA_PRESS && inv2->item_is_held){
@ -198,34 +79,30 @@ void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
} else if (i == inv->selected_item) { } else if (i == inv->selected_item) {
color = RED; color = RED;
} }
DrawRectangleLinesEco(x, y, 64, 64, color); DrawRectangleLinesEco(x, y, 64, 64, color);
if (item->quantity > 0) { if (item->quantity > 0) {
Texture2D tex = GetSpriteTexture2D(assets_find(item->kind)); DrawTexturePro(GetSpriteTexture2D(assets_find(item->kind)), ASSET_SRC_RECT(), ASSET_DST_RECT(x,y), (Vector2){0.5f,0.5f}, 0.0f, WHITE);
float aspect = tex.width/(float)tex.height;
float size = WORLD_BLOCK_SIZE * aspect;
float ofs_x = (WORLD_BLOCK_SIZE-size)/2.0f;
DrawTexturePro(tex, ASSET_SRC_RECT_TEX(tex.width, tex.height), ASSET_DST_RECT_TEX(x+ofs_x, y, size, WORLD_BLOCK_SIZE), (Vector2){0.5f,0.5f}, 0.0f, WHITE);
} }
if (item->quantity > 1) { if (item->quantity > 1) {
DrawTextEco(zpl_bprintf("%d", item->quantity), x+5, y+5, 16, RAYWHITE, 0.0f); DrawTextEco(zpl_bprintf("%d", item->quantity), x+5, y+5, 16, RAYWHITE, 0.0f);
} }
if (item->quantity > 0 && item->durability < 1.0f) { if (item->quantity > 0 && item->durability < 1.0f) {
DrawRectangleEco(x, y+56, 64, 8, BLACK); DrawRectangleEco(x, y+56, 64, 8, BLACK);
DrawRectangleEco(x, y+56, 64*item->durability, 8, BlendColor(RED, GREEN, item->durability)); DrawRectangleEco(x, y+56, 64*item->durability, 8, BlendColor(RED, GREEN, item->durability));
} }
} }
x += 64; x += 64;
if ((i+1) % inv_cols == 0) { if ((i+1) % inv_cols == 0) {
x = sx; x = sx;
y += 64; y += 64;
} }
} }
// NOTE(zaklaus): switch it off if is_player // NOTE(zaklaus): switch it off if is_player
if (is_player) if (is_player)
inv_is_storage_action = false; inv_is_storage_action = false;
@ -234,18 +111,14 @@ void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
void inventory_render_held_item(bool is_player){ void inventory_render_held_item(bool is_player){
inv_keystate *inv = (!is_player) ? &storage_inv : &player_inv; inv_keystate *inv = (!is_player) ? &storage_inv : &player_inv;
inv_keystate *inv2 = (is_player) ? &storage_inv : &player_inv; inv_keystate *inv2 = (is_player) ? &storage_inv : &player_inv;
if (inv->item_is_held) { if (inv->item_is_held) {
Vector2 mpos = GetMousePosition(); Vector2 mpos = GetMousePosition();
mpos.x -= 32; mpos.x -= 32;
mpos.y -= 32; mpos.y -= 32;
Texture2D tex = GetSpriteTexture2D(assets_find(inv->held_item.kind)); DrawTexturePro(GetSpriteTexture2D(assets_find(inv->held_item.kind)), ASSET_SRC_RECT(), ASSET_DST_RECT(mpos.x, mpos.y), (Vector2){0.5f,0.5f}, 0.0f, ColorAlpha(WHITE, 0.8f));
float aspect = tex.width/(float)tex.height;
float size = WORLD_BLOCK_SIZE * aspect;
float ofs_x = (WORLD_BLOCK_SIZE-size)/2.0f;
DrawTexturePro(tex, ASSET_SRC_RECT_TEX(tex.width, tex.height), ASSET_DST_RECT_TEX(mpos.x+ofs_x, mpos.y, size, WORLD_BLOCK_SIZE), (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); DrawTextEco(zpl_bprintf("%d", inv->held_item.quantity), mpos.x, mpos.y, 16, RAYWHITE, 0.0f);
if (!inv->is_inside && IsMouseButtonReleased(MOUSE_LEFT_BUTTON) && !inv2->is_inside) { if (!inv->is_inside && IsMouseButtonReleased(MOUSE_LEFT_BUTTON) && !inv2->is_inside) {
inv->drop_item = true; inv->drop_item = true;
inv->item_is_held = false; inv->item_is_held = false;
@ -257,7 +130,6 @@ void inventory_render_held_item(bool is_player){
void inventory_reset_states(inv_keystate *ik) { void inventory_reset_states(inv_keystate *ik) {
ik->drop_item = false; ik->drop_item = false;
ik->swap = false; ik->swap = false;
ik->craft_item = 0;
} }
void inventory_draw() { void inventory_draw() {
@ -266,22 +138,22 @@ void inventory_draw() {
inv_swap_storage = false; inv_swap_storage = false;
inventory_reset_states(&player_inv); inventory_reset_states(&player_inv);
inventory_reset_states(&storage_inv); inventory_reset_states(&storage_inv);
camera cam = camera_get(); camera cam = camera_get();
entity_view *e = game_world_view_active_get_entity(cam.ent_id); entity_view *e = game_world_view_active_get_entity(cam.ent_id);
if (!e || !e->has_items) return; if (!e || !e->has_items) return;
if (input_is_pressed(IN_TOGGLE_INV)) { if (IsKeyPressed(KEY_TAB)) {
inv_is_open = !inv_is_open; inv_is_open = !inv_is_open;
} }
if (!inv_is_open || build_is_in_draw_mode) { if (!inv_is_open || build_is_in_draw_mode) {
return; return;
} }
inventory_draw_panel(e, true, screenWidth/2.0f + 128, screenHeight/2.0f - 96); inventory_draw_panel(e, true, screenWidth/2.0f + 128, screenHeight/2.0f - 96);
inventory_draw_panel(e, false, screenWidth/2.0f - 384, screenHeight/2.0f - 128); inventory_draw_panel(e, false, screenWidth/2.0f - 384, screenHeight/2.0f - 128);
inventory_render_held_item(true); inventory_render_held_item(true);
inventory_render_held_item(false); inventory_render_held_item(false);
} }

View File

@ -1,112 +0,0 @@
#define MAX_NOTIFICATIONS_ON_SCREEN 5
typedef struct {
zpl_string title;
zpl_string text;
} notification;
static notification *notifications = 0;
static bool show_notification_list = 0;
void notification_push(const char* title1, const char* text1) {
if (!notifications) {
zpl_array_init(notifications, zpl_heap());
}
zpl_string title = zpl_string_make(zpl_heap(), title1);
zpl_string text = zpl_string_make(zpl_heap(), text1);
zpl_array_append(notifications, ((notification) { title, text }));
}
void notification_clear(void) {
for (zpl_isize i = 0; i < zpl_array_count(notifications); i++) {
zpl_string_free(notifications[i].title);
zpl_string_free(notifications[i].text);
}
zpl_array_clear(notifications);
}
void notification_draw(void) {
float width = (float)GetScreenWidth();
float height = (float)GetScreenHeight();
// draw ctrl panel
if (nk_begin(game_ui, "Notifications", nk_rect(width - 220, 20, 200, 80),
NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_TITLE | NK_WINDOW_DYNAMIC)) {
{
nk_layout_row_dynamic(game_ui, 0, 2);
if (nk_button_label(game_ui, "Clear All")) {
notification_clear();
}
if (nk_button_label(game_ui, show_notification_list ? "Hide Manager" : "Show All")) {
show_notification_list ^= 1;
}
}
nk_end(game_ui);
}
float ypos = 100;
zpl_isize cnt = zpl_min(zpl_array_count(notifications), MAX_NOTIFICATIONS_ON_SCREEN)-1;
for (zpl_isize i = cnt; i >= 0; --i) {
notification *notif = (notifications + i);
if (nk_begin_titled(game_ui, zpl_bprintf("%d%fnotif%s", i, ypos, notif->title), notif->title, nk_rect(width - 320, ypos, 300, 1200),
NK_WINDOW_DYNAMIC|NK_WINDOW_NO_SCROLLBAR)) {
{
if (nk_tree_push_id(game_ui, NK_TREE_TAB, notif->title, NK_MAXIMIZED, (int)i)) {
nk_label_wrap(game_ui, notif->text);
if (nk_button_label(game_ui, "OK")) {
zpl_string_free(notifications[i].title);
zpl_string_free(notifications[i].text);
zpl_array_remove_at(notifications, i);
}
nk_tree_pop(game_ui);
}
}
ypos += nk_window_get_panel(game_ui)->row.height + 80;
nk_end(game_ui);
}
}
if (show_notification_list) {
if (nk_begin(game_ui, "Notifications Manager", nk_rect(width/2.0f - 320, height/2.0f - 240, 640, 480),
NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_TITLE | NK_WINDOW_MOVABLE | NK_WINDOW_DYNAMIC )) {
{
nk_layout_row_dynamic(game_ui, 5 , 1);
{
for (zpl_isize i = 0; i < zpl_array_count(notifications); ++i) {
notification *notif = (notifications + i);
if (nk_tree_push_id(game_ui, NK_TREE_TAB, notif->title, NK_MINIMIZED, (int)i)) {
{
nk_label_wrap(game_ui, notif->text);
if (nk_button_label(game_ui, "OK")) {
zpl_string_free(notifications[i].title);
zpl_string_free(notifications[i].text);
zpl_array_remove_at(notifications, i); --i;
}
}
nk_tree_pop(game_ui);
}
}
}
nk_layout_row_dynamic(game_ui, 0, 2);
if (nk_button_label(game_ui, "Clear All")) {
notification_clear();
}
if (nk_button_label(game_ui, "Hide Manager")) {
show_notification_list = 0 ;
}
}
nk_end(game_ui);
}
}
}

View File

@ -1,3 +0,0 @@
#pragma once
void notification_push(const char* title, const char* text);

View File

@ -1,14 +0,0 @@
void spritesheet_viewer(struct nk_context *ctx, struct nk_image spritesheet, Vector2 frameSize, int framesPerRow) {
const int maxFrames = (int)((spritesheet.w*spritesheet.h) / (frameSize.x*frameSize.y));
nk_layout_row_static(ctx, 32, 32, (int)(nk_window_get_size(ctx).x / frameSize.x) -1);
for(int frame = 0; frame < maxFrames; frame++) {
float ox = (frame % framesPerRow) * frameSize.x;
float oy = (int)(frame / framesPerRow) * frameSize.y;
spritesheet.region[0] = (nk_ushort)ox;
spritesheet.region[1] = (nk_ushort)oy;
spritesheet.region[2] = (nk_ushort)frameSize.x;
spritesheet.region[3] = (nk_ushort)frameSize.y;
nk_image(ctx, spritesheet);
nk_labelf(ctx, NK_TEXT_ALIGN_LEFT, "%d", frame);
}
}

View File

@ -1,254 +0,0 @@
// Tooltip system with multilevel modal support
typedef struct _tooltip {
const char *name;
const char *content;
const char **links;
} tooltip;
static tooltip *tooltips = 0;
//~ registration
void tooltip_register(tooltip desc) {
if (!tooltips) {
zpl_array_init(tooltips, zpl_heap());
}
desc.links = 0;
zpl_array_append(tooltips, desc);
}
void tooltip_destroy_all(void) {
if (!tooltips) return;
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
if (tp->links) {
zpl_array_free(tp->links);
}
}
zpl_array_free(tooltips);
}
void tooltip_build_links(void) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
for (zpl_isize j = 0; j < zpl_array_count(tooltips); ++j) {
tooltip *linked_tp = (tooltips + j);
if (tp == linked_tp)
continue;
if (strstr(tp->content, linked_tp->name)) {
if (!tp->links) {
zpl_array_init(tp->links, zpl_heap());
}
zpl_array_append(tp->links, linked_tp->name);
}
}
}
}
void tooltip_register_defaults(void) {
// test
tooltip_register( (tooltip) { .name = "ASSET_WOOD", .content = "Used as a building material or fuel for the ASSET_FURNACE." } );
tooltip_register( (tooltip) { .name = "ASSET_FURNACE", .content = "Producer used to smelt ASSET_IRON_ORE into ASSET_IRON_INGOT." } );
tooltip_register( (tooltip) { .name = "ASSET_IRON_ORE", .content = "Natural resource that can be smelted in ASSET_FURNACE." } );
tooltip_register( (tooltip) { .name = "ASSET_IRON_INGOT", .content = "Used as a building material. It is smelted from ASSET_IRON_ORE." } );
tooltip_register( (tooltip) { .name = "ASSET_SCREWS", .content = "Used as a building material. It is crafted from ASSET_IRON_PLATES." } );
tooltip_register( (tooltip) { .name = "craft", .content = "Crafting is the process of constructing tools, items, and blocks." } );
tooltip_register( (tooltip) { .name = "smelt", .content = "Smelting is a process of applying heat to ore, to extract a base metal. It is a form of extractive metallurgy. It is used to extract many metals from their ores, including silver, iron, copper, and other base metals." } );
}
//~ rendering
#define TOOLTIP_MOUSE_DIST 400.0f
typedef struct _tooltip_node {
float xpos, ypos;
tooltip *desc;
struct _tooltip_node *next;
} tooltip_node;
static tooltip_node main_tooltip = { 0 };
static bool tooltip__should_stay_open = false;
tooltip *tooltip_find_desc(const char *name) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
if (!strcmp(tp->name, name))
return tp;
}
return 0;
}
const char *tooltip_find_desc_contents(const char *name) {
if (!tooltips) return 0;
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
if (!strcmp(tp->name, name))
return tp->content;
}
return 0;
}
void tooltip_clear(void);
void tooltip_show(const char* name, float xpos, float ypos) {
if (!tooltips) return;
tooltip *desc = tooltip_find_desc(name);
if (!name) return;
tooltip_clear();
main_tooltip = (tooltip_node) {
.xpos = xpos,
.ypos = ypos,
.desc = desc,
.next = 0
};
}
void tooltip_show_cursor(const char* name) {
Vector2 mpos = GetMousePosition();
tooltip_show(name, mpos.x + 15, mpos.y + 15);
}
void tooltip__clear_node(tooltip_node *node) {
if (node->next) {
tooltip__clear_node(node->next);
zpl_mfree(node->next);
}
}
void tooltip_clear(void) {
tooltip__clear_node(&main_tooltip);
main_tooltip = (tooltip_node) {0};
}
void tooltip_draw_contents(tooltip *desc) {
if (!desc) return;
nk_layout_row_dynamic(game_ui, 0, 1);
nk_label_wrap(game_ui, desc->content);
}
void tooltip__draw_node(tooltip_node *node) {
if (!node) return;
if (!node->desc) return;
tooltip *desc = node->desc;
Vector2 mpos = GetMousePosition();
if (nk_begin_titled(game_ui, zpl_bprintf("%d%s", (int)node->xpos, desc->name), desc->name, nk_rect(node->xpos, node->ypos, 500, 3200),
NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_DYNAMIC | NK_WINDOW_TITLE | NK_WINDOW_MOVABLE)) {
tooltip_draw_contents(desc);
if (desc->links) {
nk_label(game_ui, "See Also:", NK_TEXT_LEFT);
nk_layout_row_dynamic(game_ui, 20, 2);
for (zpl_isize i = 0; i < zpl_array_count(desc->links); ++i) {
if (nk_button_label(game_ui, desc->links[i])) {
if (node->next) tooltip__clear_node(node->next);
if (!node->next) node->next = zpl_malloc(sizeof(tooltip_node));
*node->next = (tooltip_node) {
.xpos = mpos.x+15,
.ypos = mpos.y+15,
.desc = tooltip_find_desc(desc->links[i]),
.next = 0
};
}
}
}
// suggest closing tooltip
struct nk_vec2 wpos = nk_window_get_position(game_ui);
struct nk_vec2 wsize = nk_window_get_content_region_size(game_ui);
struct nk_panel *wpanel = nk_window_get_panel(game_ui);
Vector2 tp_pos = (Vector2) { .x = wpos.x + wsize.x/2.0f, .y = wpos.y + wpanel->row.height / 2.0f };
if (Vector2Distance(mpos, tp_pos) <= TOOLTIP_MOUSE_DIST) {
tooltip__should_stay_open = true;
}
#if 0
{
DrawCircleV(tp_pos, TOOLTIP_MOUSE_DIST, BLUE);
}
#endif
nk_end(game_ui);
// draw nested tooltip
if (node->next) {
tooltip__draw_node(node->next);
}
}
}
void tooltip_draw(void) {
// draw tooltip
tooltip__draw_node(&main_tooltip);
if (!tooltip__should_stay_open) {
tooltip_clear();
}
tooltip__should_stay_open = false;
// draw search bar
float width = (float)GetScreenWidth();
float height = (float)GetScreenHeight();
if (nk_begin(game_ui, "#searchbar", nk_rect(width / 2.0f - 200, 15.f, 400, 600), NK_WINDOW_DYNAMIC | NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR)) {
{
static int len=0; static char buffer[256] = { 0 };
static bool show_all = false;
if (len > 0) {
nk_layout_row_dynamic(game_ui, 15, 1);
if (nk_button_label(game_ui, "clear all")) {
len = 0;
}
}
nk_layout_row_dynamic(game_ui, 35, 1);
if (!(nk_edit_string(game_ui, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_ascii) & NK_WIDGET_STATE_ACTIVE) && len == 0 ) {
show_all = true;
}
buffer[len] = 0;
if (len > 0 || show_all) {
if (nk_tree_push(game_ui, NK_TREE_TAB, "results", NK_MAXIMIZED)) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i);
if (strstr(tp->name, buffer) || show_all) {
if (nk_button_label(game_ui, tp->name)) {
tooltip_show_cursor(tp->name);
}
}
}
nk_tree_pop(game_ui);
}
}
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) || len > 0) {
show_all = false;
}
}
nk_end(game_ui);
}
}

View File

@ -1,483 +0,0 @@
enum theme {THEME_BLACK, THEME_WHITE, THEME_RED, THEME_BLUE, THEME_DARK, THEME_ECO};
static void set_style(struct nk_context *ctx, enum theme theme)
{
struct nk_color table[NK_COLOR_COUNT];
if (theme == THEME_WHITE) {
table[NK_COLOR_TEXT] = nk_rgba(70, 70, 70, 255);
table[NK_COLOR_WINDOW] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_HEADER] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_BORDER] = nk_rgba(0, 0, 0, 255);
table[NK_COLOR_BUTTON] = nk_rgba(185, 185, 185, 255);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(170, 170, 170, 255);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(160, 160, 160, 255);
table[NK_COLOR_TOGGLE] = nk_rgba(150, 150, 150, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(120, 120, 120, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_SELECT] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_SLIDER] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(80, 80, 80, 255);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(70, 70, 70, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(60, 60, 60, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_EDIT] = nk_rgba(150, 150, 150, 255);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(0, 0, 0, 255);
table[NK_COLOR_COMBO] = nk_rgba(175, 175, 175, 255);
table[NK_COLOR_CHART] = nk_rgba(160, 160, 160, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(45, 45, 45, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(180, 180, 180, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(140, 140, 140, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(150, 150, 150, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(160, 160, 160, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(180, 180, 180, 255);
nk_style_from_table(ctx, table);
} else if (theme == THEME_RED) {
table[NK_COLOR_TEXT] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_WINDOW] = nk_rgba(30, 33, 40, 215);
table[NK_COLOR_HEADER] = nk_rgba(181, 45, 69, 220);
table[NK_COLOR_BORDER] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_BUTTON] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(190, 50, 70, 255);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(195, 55, 75, 255);
table[NK_COLOR_TOGGLE] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 60, 60, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SELECT] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SLIDER] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(186, 50, 74, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(191, 55, 79, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_EDIT] = nk_rgba(51, 55, 67, 225);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_COMBO] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_CHART] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(170, 40, 60, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(30, 33, 40, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(181, 45, 69, 220);
nk_style_from_table(ctx, table);
} else if (theme == THEME_ECO) {
table[NK_COLOR_TEXT] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_WINDOW] = nk_rgba(40, 43, 10, 235);
table[NK_COLOR_HEADER] = nk_rgba(32, 96, 64 , 220);
table[NK_COLOR_BORDER] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_BUTTON] = nk_rgba(20, 23, 30, 215);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(32, 96, 64 , 235);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(52, 116, 84 , 255);
table[NK_COLOR_TOGGLE] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 60, 60, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SELECT] = nk_rgba(20, 23, 30, 215);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SLIDER] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(181, 45, 69, 255);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(186, 50, 74, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(191, 55, 79, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_EDIT] = nk_rgba(51, 55, 67, 225);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(190, 190, 190, 255);
table[NK_COLOR_COMBO] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_CHART] = nk_rgba(51, 55, 67, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(170, 40, 60, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(30, 33, 40, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(32, 96, 64 , 220);
nk_style_from_table(ctx, table);
} else if (theme == THEME_BLUE) {
table[NK_COLOR_TEXT] = nk_rgba(20, 20, 20, 255);
table[NK_COLOR_WINDOW] = nk_rgba(202, 212, 214, 215);
table[NK_COLOR_HEADER] = nk_rgba(137, 182, 224, 220);
table[NK_COLOR_BORDER] = nk_rgba(140, 159, 173, 255);
table[NK_COLOR_BUTTON] = nk_rgba(137, 182, 224, 255);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(142, 187, 229, 255);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(147, 192, 234, 255);
table[NK_COLOR_TOGGLE] = nk_rgba(177, 210, 210, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(182, 215, 215, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(137, 182, 224, 255);
table[NK_COLOR_SELECT] = nk_rgba(177, 210, 210, 255);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(137, 182, 224, 255);
table[NK_COLOR_SLIDER] = nk_rgba(177, 210, 210, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(137, 182, 224, 245);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(142, 188, 229, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(147, 193, 234, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_EDIT] = nk_rgba(210, 210, 210, 225);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(20, 20, 20, 255);
table[NK_COLOR_COMBO] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_CHART] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(137, 182, 224, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(190, 200, 200, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(156, 193, 220, 255);
nk_style_from_table(ctx, table);
} else if (theme == THEME_DARK) {
table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_WINDOW] = nk_rgba(57, 67, 71, 215);
table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 220);
table[NK_COLOR_BORDER] = nk_rgba(46, 46, 46, 255);
table[NK_COLOR_BUTTON] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_BUTTON_HOVER] = nk_rgba(58, 93, 121, 255);
table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(63, 98, 126, 255);
table[NK_COLOR_TOGGLE] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 53, 56, 255);
table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_SELECT] = nk_rgba(57, 67, 61, 255);
table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_SLIDER] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(48, 83, 111, 245);
table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255);
table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255);
table[NK_COLOR_PROPERTY] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_EDIT] = nk_rgba(50, 58, 61, 225);
table[NK_COLOR_EDIT_CURSOR] = nk_rgba(210, 210, 210, 255);
table[NK_COLOR_COMBO] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_CHART] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_CHART_COLOR] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba(255, 0, 0, 255);
table[NK_COLOR_SCROLLBAR] = nk_rgba(50, 58, 61, 255);
table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(48, 83, 111, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255);
table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255);
table[NK_COLOR_TAB_HEADER] = nk_rgba(48, 83, 111, 255);
nk_style_from_table(ctx, table);
} else {
nk_style_default(ctx);
}
}
#if 0
typedef struct media {
GLint skin;
struct nk_image menu;
struct nk_image check;
struct nk_image check_cursor;
struct nk_image option;
struct nk_image option_cursor;
struct nk_image header;
struct nk_image window;
struct nk_image scrollbar_inc_button;
struct nk_image scrollbar_inc_button_hover;
struct nk_image scrollbar_dec_button;
struct nk_image scrollbar_dec_button_hover;
struct nk_image button;
struct nk_image button_hover;
struct nk_image button_active;
struct nk_image tab_minimize;
struct nk_image tab_maximize;
struct nk_image slider;
struct nk_image slider_hover;
struct nk_image slider_active;
} media;
void nk_skin_gwen(void) {
media.skin = image_load("../skins/gwen.png");
media.check = nk_subimage_id(media.skin, 512,512, nk_rect(464,32,15,15));
media.check_cursor = nk_subimage_id(media.skin, 512,512, nk_rect(450,34,11,11));
media.option = nk_subimage_id(media.skin, 512,512, nk_rect(464,64,15,15));
media.option_cursor = nk_subimage_id(media.skin, 512,512, nk_rect(451,67,9,9));
media.header = nk_subimage_id(media.skin, 512,512, nk_rect(128,0,127,24));
media.window = nk_subimage_id(media.skin, 512,512, nk_rect(128,23,127,104));
media.scrollbar_inc_button = nk_subimage_id(media.skin, 512,512, nk_rect(464,256,15,15));
media.scrollbar_inc_button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(464,320,15,15));
media.scrollbar_dec_button = nk_subimage_id(media.skin, 512,512, nk_rect(464,224,15,15));
media.scrollbar_dec_button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(464,288,15,15));
media.button = nk_subimage_id(media.skin, 512,512, nk_rect(384,336,127,31));
media.button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(384,368,127,31));
media.button_active = nk_subimage_id(media.skin, 512,512, nk_rect(384,400,127,31));
media.tab_minimize = nk_subimage_id(media.skin, 512,512, nk_rect(451, 99, 9, 9));
media.tab_maximize = nk_subimage_id(media.skin, 512,512, nk_rect(467,99,9,9));
media.slider = nk_subimage_id(media.skin, 512,512, nk_rect(418,33,11,14));
media.slider_hover = nk_subimage_id(media.skin, 512,512, nk_rect(418,49,11,14));
media.slider_active = nk_subimage_id(media.skin, 512,512, nk_rect(418,64,11,14));
/* window */
ctx.style.window.background = nk_rgb(204,204,204);
ctx.style.window.fixed_background = nk_style_item_image(media.window);
ctx.style.window.border_color = nk_rgb(67,67,67);
ctx.style.window.combo_border_color = nk_rgb(67,67,67);
ctx.style.window.contextual_border_color = nk_rgb(67,67,67);
ctx.style.window.menu_border_color = nk_rgb(67,67,67);
ctx.style.window.group_border_color = nk_rgb(67,67,67);
ctx.style.window.tooltip_border_color = nk_rgb(67,67,67);
ctx.style.window.scrollbar_size = nk_vec2(16,16);
ctx.style.window.border_color = nk_rgba(0,0,0,0);
ctx.style.window.padding = nk_vec2(8,4);
ctx.style.window.border = 3;
/* window header */
ctx.style.window.header.normal = nk_style_item_image(media.header);
ctx.style.window.header.hover = nk_style_item_image(media.header);
ctx.style.window.header.active = nk_style_item_image(media.header);
ctx.style.window.header.label_normal = nk_rgb(95,95,95);
ctx.style.window.header.label_hover = nk_rgb(95,95,95);
ctx.style.window.header.label_active = nk_rgb(95,95,95);
/* scrollbar */
ctx.style.scrollv.normal = nk_style_item_color(nk_rgb(184,184,184));
ctx.style.scrollv.hover = nk_style_item_color(nk_rgb(184,184,184));
ctx.style.scrollv.active = nk_style_item_color(nk_rgb(184,184,184));
ctx.style.scrollv.cursor_normal = nk_style_item_color(nk_rgb(220,220,220));
ctx.style.scrollv.cursor_hover = nk_style_item_color(nk_rgb(235,235,235));
ctx.style.scrollv.cursor_active = nk_style_item_color(nk_rgb(99,202,255));
ctx.style.scrollv.dec_symbol = NK_SYMBOL_NONE;
ctx.style.scrollv.inc_symbol = NK_SYMBOL_NONE;
ctx.style.scrollv.show_buttons = nk_true;
ctx.style.scrollv.border_color = nk_rgb(81,81,81);
ctx.style.scrollv.cursor_border_color = nk_rgb(81,81,81);
ctx.style.scrollv.border = 1;
ctx.style.scrollv.rounding = 0;
ctx.style.scrollv.border_cursor = 1;
ctx.style.scrollv.rounding_cursor = 2;
/* scrollbar buttons */
ctx.style.scrollv.inc_button.normal = nk_style_item_image(media.scrollbar_inc_button);
ctx.style.scrollv.inc_button.hover = nk_style_item_image(media.scrollbar_inc_button_hover);
ctx.style.scrollv.inc_button.active = nk_style_item_image(media.scrollbar_inc_button_hover);
ctx.style.scrollv.inc_button.border_color = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.text_background = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.text_active = nk_rgba(0,0,0,0);
ctx.style.scrollv.inc_button.border = 0.0f;
ctx.style.scrollv.dec_button.normal = nk_style_item_image(media.scrollbar_dec_button);
ctx.style.scrollv.dec_button.hover = nk_style_item_image(media.scrollbar_dec_button_hover);
ctx.style.scrollv.dec_button.active = nk_style_item_image(media.scrollbar_dec_button_hover);
ctx.style.scrollv.dec_button.border_color = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.text_background = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.text_active = nk_rgba(0,0,0,0);
ctx.style.scrollv.dec_button.border = 0.0f;
/* checkbox toggle */
{struct nk_style_toggle *toggle;
toggle = &ctx.style.checkbox;
toggle->normal = nk_style_item_image(media.check);
toggle->hover = nk_style_item_image(media.check);
toggle->active = nk_style_item_image(media.check);
toggle->cursor_normal = nk_style_item_image(media.check_cursor);
toggle->cursor_hover = nk_style_item_image(media.check_cursor);
toggle->text_normal = nk_rgb(95,95,95);
toggle->text_hover = nk_rgb(95,95,95);
toggle->text_active = nk_rgb(95,95,95);}
/* option toggle */
{struct nk_style_toggle *toggle;
toggle = &ctx.style.option;
toggle->normal = nk_style_item_image(media.option);
toggle->hover = nk_style_item_image(media.option);
toggle->active = nk_style_item_image(media.option);
toggle->cursor_normal = nk_style_item_image(media.option_cursor);
toggle->cursor_hover = nk_style_item_image(media.option_cursor);
toggle->text_normal = nk_rgb(95,95,95);
toggle->text_hover = nk_rgb(95,95,95);
toggle->text_active = nk_rgb(95,95,95);}
/* default button */
ctx.style.button.normal = nk_style_item_image(media.button);
ctx.style.button.hover = nk_style_item_image(media.button_hover);
ctx.style.button.active = nk_style_item_image(media.button_active);
ctx.style.button.border_color = nk_rgba(0,0,0,0);
ctx.style.button.text_background = nk_rgba(0,0,0,0);
ctx.style.button.text_normal = nk_rgb(95,95,95);
ctx.style.button.text_hover = nk_rgb(95,95,95);
ctx.style.button.text_active = nk_rgb(95,95,95);
/* default text */
ctx.style.text.color = nk_rgb(95,95,95);
/* contextual button */
ctx.style.contextual_button.normal = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.contextual_button.hover = nk_style_item_color(nk_rgb(229,229,229));
ctx.style.contextual_button.active = nk_style_item_color(nk_rgb(99,202,255));
ctx.style.contextual_button.border_color = nk_rgba(0,0,0,0);
ctx.style.contextual_button.text_background = nk_rgba(0,0,0,0);
ctx.style.contextual_button.text_normal = nk_rgb(95,95,95);
ctx.style.contextual_button.text_hover = nk_rgb(95,95,95);
ctx.style.contextual_button.text_active = nk_rgb(95,95,95);
/* menu button */
ctx.style.menu_button.normal = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.menu_button.hover = nk_style_item_color(nk_rgb(229,229,229));
ctx.style.menu_button.active = nk_style_item_color(nk_rgb(99,202,255));
ctx.style.menu_button.border_color = nk_rgba(0,0,0,0);
ctx.style.menu_button.text_background = nk_rgba(0,0,0,0);
ctx.style.menu_button.text_normal = nk_rgb(95,95,95);
ctx.style.menu_button.text_hover = nk_rgb(95,95,95);
ctx.style.menu_button.text_active = nk_rgb(95,95,95);
/* tree */
ctx.style.tab.text = nk_rgb(95,95,95);
ctx.style.tab.tab_minimize_button.normal = nk_style_item_image(media.tab_minimize);
ctx.style.tab.tab_minimize_button.hover = nk_style_item_image(media.tab_minimize);
ctx.style.tab.tab_minimize_button.active = nk_style_item_image(media.tab_minimize);
ctx.style.tab.tab_minimize_button.text_background = nk_rgba(0,0,0,0);
ctx.style.tab.tab_minimize_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.tab.tab_minimize_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.tab.tab_minimize_button.text_active = nk_rgba(0,0,0,0);
ctx.style.tab.tab_maximize_button.normal = nk_style_item_image(media.tab_maximize);
ctx.style.tab.tab_maximize_button.hover = nk_style_item_image(media.tab_maximize);
ctx.style.tab.tab_maximize_button.active = nk_style_item_image(media.tab_maximize);
ctx.style.tab.tab_maximize_button.text_background = nk_rgba(0,0,0,0);
ctx.style.tab.tab_maximize_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.tab.tab_maximize_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.tab.tab_maximize_button.text_active = nk_rgba(0,0,0,0);
ctx.style.tab.node_minimize_button.normal = nk_style_item_image(media.tab_minimize);
ctx.style.tab.node_minimize_button.hover = nk_style_item_image(media.tab_minimize);
ctx.style.tab.node_minimize_button.active = nk_style_item_image(media.tab_minimize);
ctx.style.tab.node_minimize_button.text_background = nk_rgba(0,0,0,0);
ctx.style.tab.node_minimize_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.tab.node_minimize_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.tab.node_minimize_button.text_active = nk_rgba(0,0,0,0);
ctx.style.tab.node_maximize_button.normal = nk_style_item_image(media.tab_maximize);
ctx.style.tab.node_maximize_button.hover = nk_style_item_image(media.tab_maximize);
ctx.style.tab.node_maximize_button.active = nk_style_item_image(media.tab_maximize);
ctx.style.tab.node_maximize_button.text_background = nk_rgba(0,0,0,0);
ctx.style.tab.node_maximize_button.text_normal = nk_rgba(0,0,0,0);
ctx.style.tab.node_maximize_button.text_hover = nk_rgba(0,0,0,0);
ctx.style.tab.node_maximize_button.text_active = nk_rgba(0,0,0,0);
/* selectable */
ctx.style.selectable.normal = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.selectable.hover = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.selectable.pressed = nk_style_item_color(nk_rgb(206,206,206));
ctx.style.selectable.normal_active = nk_style_item_color(nk_rgb(185,205,248));
ctx.style.selectable.hover_active = nk_style_item_color(nk_rgb(185,205,248));
ctx.style.selectable.pressed_active = nk_style_item_color(nk_rgb(185,205,248));
ctx.style.selectable.text_normal = nk_rgb(95,95,95);
ctx.style.selectable.text_hover = nk_rgb(95,95,95);
ctx.style.selectable.text_pressed = nk_rgb(95,95,95);
ctx.style.selectable.text_normal_active = nk_rgb(95,95,95);
ctx.style.selectable.text_hover_active = nk_rgb(95,95,95);
ctx.style.selectable.text_pressed_active = nk_rgb(95,95,95);
/* slider */
ctx.style.slider.normal = nk_style_item_hide();
ctx.style.slider.hover = nk_style_item_hide();
ctx.style.slider.active = nk_style_item_hide();
ctx.style.slider.bar_normal = nk_rgb(156,156,156);
ctx.style.slider.bar_hover = nk_rgb(156,156,156);
ctx.style.slider.bar_active = nk_rgb(156,156,156);
ctx.style.slider.bar_filled = nk_rgb(156,156,156);
ctx.style.slider.cursor_normal = nk_style_item_image(media.slider);
ctx.style.slider.cursor_hover = nk_style_item_image(media.slider_hover);
ctx.style.slider.cursor_active = nk_style_item_image(media.slider_active);
ctx.style.slider.cursor_size = nk_vec2(16.5f,21);
ctx.style.slider.bar_height = 1;
/* progressbar */
ctx.style.progress.normal = nk_style_item_color(nk_rgb(231,231,231));
ctx.style.progress.hover = nk_style_item_color(nk_rgb(231,231,231));
ctx.style.progress.active = nk_style_item_color(nk_rgb(231,231,231));
ctx.style.progress.cursor_normal = nk_style_item_color(nk_rgb(63,242,93));
ctx.style.progress.cursor_hover = nk_style_item_color(nk_rgb(63,242,93));
ctx.style.progress.cursor_active = nk_style_item_color(nk_rgb(63,242,93));
ctx.style.progress.border_color = nk_rgb(114,116,115);
ctx.style.progress.padding = nk_vec2(0,0);
ctx.style.progress.border = 2;
ctx.style.progress.rounding = 1;
/* combo */
ctx.style.combo.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.border_color = nk_rgb(95,95,95);
ctx.style.combo.label_normal = nk_rgb(95,95,95);
ctx.style.combo.label_hover = nk_rgb(95,95,95);
ctx.style.combo.label_active = nk_rgb(95,95,95);
ctx.style.combo.border = 1;
ctx.style.combo.rounding = 1;
/* combo button */
ctx.style.combo.button.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.button.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.button.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.combo.button.text_background = nk_rgb(216,216,216);
ctx.style.combo.button.text_normal = nk_rgb(95,95,95);
ctx.style.combo.button.text_hover = nk_rgb(95,95,95);
ctx.style.combo.button.text_active = nk_rgb(95,95,95);
/* property */
ctx.style.property.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.border_color = nk_rgb(81,81,81);
ctx.style.property.label_normal = nk_rgb(95,95,95);
ctx.style.property.label_hover = nk_rgb(95,95,95);
ctx.style.property.label_active = nk_rgb(95,95,95);
ctx.style.property.sym_left = NK_SYMBOL_TRIANGLE_LEFT;
ctx.style.property.sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
ctx.style.property.rounding = 10;
ctx.style.property.border = 1;
/* edit */
ctx.style.edit.normal = nk_style_item_color(nk_rgb(240,240,240));
ctx.style.edit.hover = nk_style_item_color(nk_rgb(240,240,240));
ctx.style.edit.active = nk_style_item_color(nk_rgb(240,240,240));
ctx.style.edit.border_color = nk_rgb(62,62,62);
ctx.style.edit.cursor_normal = nk_rgb(99,202,255);
ctx.style.edit.cursor_hover = nk_rgb(99,202,255);
ctx.style.edit.cursor_text_normal = nk_rgb(95,95,95);
ctx.style.edit.cursor_text_hover = nk_rgb(95,95,95);
ctx.style.edit.text_normal = nk_rgb(95,95,95);
ctx.style.edit.text_hover = nk_rgb(95,95,95);
ctx.style.edit.text_active = nk_rgb(95,95,95);
ctx.style.edit.selected_normal = nk_rgb(99,202,255);
ctx.style.edit.selected_hover = nk_rgb(99,202,255);
ctx.style.edit.selected_text_normal = nk_rgb(95,95,95);
ctx.style.edit.selected_text_hover = nk_rgb(95,95,95);
ctx.style.edit.border = 1;
ctx.style.edit.rounding = 2;
/* property buttons */
ctx.style.property.dec_button.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.dec_button.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.dec_button.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.dec_button.text_background = nk_rgba(0,0,0,0);
ctx.style.property.dec_button.text_normal = nk_rgb(95,95,95);
ctx.style.property.dec_button.text_hover = nk_rgb(95,95,95);
ctx.style.property.dec_button.text_active = nk_rgb(95,95,95);
ctx.style.property.inc_button = ctx.style.property.dec_button;
/* property edit */
ctx.style.property.edit.normal = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.edit.hover = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.edit.active = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.property.edit.border_color = nk_rgba(0,0,0,0);
ctx.style.property.edit.cursor_normal = nk_rgb(95,95,95);
ctx.style.property.edit.cursor_hover = nk_rgb(95,95,95);
ctx.style.property.edit.cursor_text_normal = nk_rgb(216,216,216);
ctx.style.property.edit.cursor_text_hover = nk_rgb(216,216,216);
ctx.style.property.edit.text_normal = nk_rgb(95,95,95);
ctx.style.property.edit.text_hover = nk_rgb(95,95,95);
ctx.style.property.edit.text_active = nk_rgb(95,95,95);
ctx.style.property.edit.selected_normal = nk_rgb(95,95,95);
ctx.style.property.edit.selected_hover = nk_rgb(95,95,95);
ctx.style.property.edit.selected_text_normal = nk_rgb(216,216,216);
ctx.style.property.edit.selected_text_hover = nk_rgb(216,216,216);
/* chart */
ctx.style.chart.background = nk_style_item_color(nk_rgb(216,216,216));
ctx.style.chart.border_color = nk_rgb(81,81,81);
ctx.style.chart.color = nk_rgb(95,95,95);
ctx.style.chart.selected_color = nk_rgb(255,0,0);
ctx.style.chart.border = 1;
}
#endif

View File

@ -0,0 +1,46 @@
#pragma once
#define ASSET_INVALID 0xFF
typedef enum {
// NOTE(zaklaus): Debug
ASSET_EMPTY,
ASSET_BLANK,
ASSET_BLOCK_FRAME,
ASSET_BUILDMODE_HIGHLIGHT,
ASSET_BIG_TREE,
// NOTE(zaklaus): entities
ASSET_PLAYER,
ASSET_THING,
ASSET_CHEST,
ASSET_FURNACE,
ASSET_BLUEPRINT,
// NOTE(zaklaus): items
// NOTE(zaklaus): blocks
ASSET_FENCE,
ASSET_DEV,
ASSET_GROUND,
ASSET_DIRT,
ASSET_WATER,
ASSET_LAVA,
ASSET_WALL,
ASSET_HILL,
ASSET_HILL_SNOW,
ASSET_HOLE,
ASSET_WOOD,
ASSET_TREE,
ASSET_COAL,
ASSET_IRON_ORE,
ASSET_IRON_INGOT,
ASSET_BELT,
ASSET_BELT_LEFT,
ASSET_BELT_RIGHT,
ASSET_BELT_UP,
ASSET_BELT_DOWN,
MAX_ASSETS = 1024,
} asset_id;

View File

@ -0,0 +1,44 @@
#include "models/assets.h"
#define ASSET_ENTRY(asset, asset_kind)\
{\
.id = asset,\
.kind = asset_kind,\
}
#define ASSET_SND(asset) ASSET_ENTRY(asset, AKIND_SOUND)
#define ASSET_TEX(asset) ASSET_ENTRY(asset, AKIND_TEXTURE)
#define ASSET_ANI(asset) ASSET_ENTRY(asset, AKIND_ANIM)
static asset assets[] = {
ASSET_TEX(ASSET_EMPTY),
ASSET_TEX(ASSET_BLANK),
ASSET_TEX(ASSET_BLOCK_FRAME),
ASSET_TEX(ASSET_BUILDMODE_HIGHLIGHT),
ASSET_TEX(ASSET_BIG_TREE),
ASSET_TEX(ASSET_COAL),
ASSET_TEX(ASSET_CHEST),
ASSET_TEX(ASSET_FURNACE),
ASSET_TEX(ASSET_BLUEPRINT),
// NOTE(zaklaus): blocks
ASSET_TEX(ASSET_FENCE),
ASSET_TEX(ASSET_DEV),
ASSET_TEX(ASSET_GROUND),
ASSET_TEX(ASSET_DIRT),
ASSET_ANI(ASSET_WATER),
ASSET_TEX(ASSET_LAVA),
ASSET_TEX(ASSET_WALL),
ASSET_TEX(ASSET_HILL),
ASSET_TEX(ASSET_HILL_SNOW),
ASSET_TEX(ASSET_HOLE),
ASSET_TEX(ASSET_WOOD),
ASSET_TEX(ASSET_TREE),
ASSET_TEX(ASSET_BELT),
ASSET_TEX(ASSET_BELT_LEFT),
ASSET_TEX(ASSET_BELT_RIGHT),
ASSET_TEX(ASSET_BELT_UP),
ASSET_TEX(ASSET_BELT_DOWN),
};

View File

@ -0,0 +1,29 @@
#include "world/blocks.h"
#define BLOCK(a, f, s, ...)\
{\
.kind = a, .flags = f, .symbol = s, __VA_ARGS__\
}
static block blocks[] = {
BLOCK(ASSET_EMPTY, 0, 'E'),
BLOCK(ASSET_GROUND, 0, '.', .drag = 1.0f, .friction = 1.0f),
BLOCK(ASSET_DIRT, 0, ',', .drag = 2.1f , .friction = 1.0f),
BLOCK(ASSET_WALL, BLOCK_FLAG_COLLISION, '#', .drag = 1.0f , .friction = 1.0f, .bounce = 1.0f),
BLOCK(ASSET_HILL, BLOCK_FLAG_COLLISION, '^', .drag = 1.0f , .friction = 1.0f),
BLOCK(ASSET_HILL_SNOW, BLOCK_FLAG_COLLISION, '*', .drag = 1.0f , .friction = 1.0f),
BLOCK(ASSET_WATER, 0, '~', .drag = 0.11f , .friction = 1.0f),
BLOCK(ASSET_LAVA, BLOCK_FLAG_HAZARD, '!', .drag = 6.2f , .friction = 4.0f),
BLOCK(ASSET_FENCE, BLOCK_FLAG_COLLISION, '[', .drag = 1.0f , .friction = 1.0f, .bounce = 1.0f),
BLOCK(ASSET_WOOD, BLOCK_FLAG_COLLISION, ']', .drag = 1.0f , .friction = 1.0f, .bounce = 0.0f),
BLOCK(ASSET_TREE, BLOCK_FLAG_COLLISION|BLOCK_FLAG_DESTROY_ON_COLLISION, '@', .drag = 1.0f , .friction = 1.0f, .bounce = 0.0f),
BLOCK(ASSET_CHEST, BLOCK_FLAG_ENTITY, 'C'),
BLOCK(ASSET_FURNACE, BLOCK_FLAG_ENTITY, 'F'),
BLOCK(ASSET_BELT_LEFT, 0, '@', .drag = 1.0f , .friction = 1.0f, .velx = -150.0f),
BLOCK(ASSET_BELT_RIGHT, 0, '@', .drag = 1.0f , .friction = 1.0f, .velx = 150.0f),
BLOCK(ASSET_BELT_UP, 0, '@', .drag = 1.0f , .friction = 1.0f, .vely = -150.0f),
BLOCK(ASSET_BELT_DOWN, 0, '@', .drag = 1.0f , .friction = 1.0f, .vely = 150.0f),
};
ZPL_STATIC_ASSERT(sizeof(blocks)/sizeof(block) < ZPL_U16_MAX, "too many registered blocks! (max. 65536)");

View File

@ -0,0 +1,16 @@
// NOTE(zaklaus): access to spawners
#include "models/prefabs/storage.h"
#include "models/prefabs/furnace.h"
#include "models/prefabs/blueprint.h"
static struct {
asset_id id;
uint64_t (*proc)();
uint64_t (*proc_udata)(void*);
} entity_spawnlist[] = {
{ .id = ASSET_CHEST, .proc = storage_spawn },
{ .id = ASSET_FURNACE, .proc = furnace_spawn },
{ .id = ASSET_BLUEPRINT, .proc_udata = blueprint_spawn_udata },
};
#define MAX_ENTITY_SPAWNDEFS ((sizeof(entity_spawnlist))/(sizeof(entity_spawnlist[0])))

View File

@ -0,0 +1,27 @@
#include "models/items.h"
#include "world/entity_view.h"
#include "items_list_helpers.h"
static item_desc items[] = {
{ .kind = 0, .max_quantity = 0, },
ITEM_INGREDIENT(ASSET_COAL, 64, ASSET_FURNACE, ASSET_BELT, 0),
ITEM_SELF(ASSET_FENCE, 64),
ITEM_ENERGY(ASSET_WOOD, ASSET_FURNACE, 64, 15.0f),
ITEM_HOLD(ASSET_TREE, 64),
// ITEM_BLUEPRINT(ASSET_BLUEPRINT, 1, 4, 4, "]]]]]CF] ]]]]]"),
ITEM_BLUEPRINT(ASSET_BLUEPRINT, 1, 4, 4, PROT({ ASSET_WOOD,ASSET_WOOD,ASSET_WOOD,ASSET_WOOD,
ASSET_WOOD,ASSET_FURNACE,ASSET_CHEST,ASSET_WOOD,
ASSET_FENCE,ASSET_EMPTY,ASSET_EMPTY,ASSET_WOOD,
ASSET_WALL,ASSET_EMPTY,ASSET_EMPTY,ASSET_WOOD})),
ITEM_SELF_DIR(ASSET_BELT, 999),
ITEM_PROXY(ASSET_BELT_LEFT, ASSET_BELT),
ITEM_PROXY(ASSET_BELT_RIGHT, ASSET_BELT),
ITEM_PROXY(ASSET_BELT_UP, ASSET_BELT),
ITEM_PROXY(ASSET_BELT_DOWN, ASSET_BELT),
ITEM_ENT(ASSET_CHEST, 32, ASSET_CHEST),
ITEM_ENT(ASSET_FURNACE, 32, ASSET_FURNACE),
ITEM_ENT(ASSET_BIG_TREE, 32, ASSET_FURNACE),
};

View File

@ -0,0 +1,105 @@
#pragma once
#define ITEM_HOLD(asset, qty, ...)\
{\
.kind = asset,\
.usage = UKIND_HOLD,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\
__VA_ARGS__\
}
#define ITEM_ENERGY(asset, producer_asset, qty, energy_value, ...)\
{\
.kind = asset,\
.usage = UKIND_HOLD,\
.attachment = UDATA_ENERGY_SOURCE,\
.max_quantity = qty,\
.energy_source = {\
.producer = producer_asset,\
.energy_level = energy_value\
},\
__VA_ARGS__\
}
#define ITEM_BLUEPRINT(asset, qty, w_, h_, plan_, ...)\
{\
.kind = asset,\
.usage = UKIND_PLACE_ITEM_DATA,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\
.blueprint = {\
.w = w_,\
.h = h_,\
.plan = (const asset_id[])plan_\
},\
.place_item = {\
.id = asset\
},\
__VA_ARGS__\
}
#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,\
},\
__VA_ARGS__\
}
#define ITEM_BLOCK(asset, qty, build_asset, ...)\
{\
.kind = asset,\
.usage = UKIND_PLACE,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\
.place = {\
.kind = build_asset,\
},\
__VA_ARGS__\
}
#define ITEM_BLOCK_DIR(asset, qty, build_asset, ...)\
{\
.kind = asset,\
.usage = UKIND_PLACE,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\
.place = {\
.kind = build_asset,\
.directional = true,\
},\
__VA_ARGS__\
}
#define ITEM_PROXY(asset, proxy_id, ...)\
{\
.kind = asset,\
.usage = UKIND_PROXY,\
.attachment = UDATA_NONE,\
.proxy = {\
.id = proxy_id,\
},\
__VA_ARGS__\
}
#define ITEM_ENT(asset, qty, eid, ...)\
{\
.kind = asset,\
.usage = UKIND_PLACE_ITEM,\
.attachment = UDATA_NONE,\
.max_quantity = qty,\
.place_item = {\
.id = eid\
},\
__VA_ARGS__\
}
#define ITEM_SELF(asset, qty, ...) ITEM_BLOCK(asset, qty, asset, __VA_ARGS__)
#define ITEM_SELF_DIR(asset, qty, ...) ITEM_BLOCK_DIR(asset, qty, asset, __VA_ARGS__)

View File

@ -1,79 +1,47 @@
#include "models/assets.h" #include "models/assets.h"
#include "raylib.h" #include "raylib.h"
#include "gen/texgen.h" #include "gen/texgen.h"
#include "models/database.h"
#include <stdint.h>
//#define ASSETS_COUNT (sizeof(assets)/sizeof(asset)) #define ASSETS_COUNT (sizeof(assets)/sizeof(asset))
typedef struct { typedef struct {
asset_id id; asset_id id;
asset_kind kind; asset_kind kind;
union { union {
Texture2D tex; Texture2D tex;
Sound snd; Sound snd;
}; };
// NOTE(zaklaus): metadata // NOTE(zaklaus): metadata
} asset; } asset;
//#include "lists/assets_list.c" #include "lists/assets_list.c"
static asset *assets;
#define ASSETS_COUNT (zpl_array_count(assets)) #define ASSET_FRAME_RENDER_MS (1.0/5.0)
#define ASSET_FRAME_RENDER_MS (1.0/1.0)
#define ASSET_FRAME_SKIP 4 #define ASSET_FRAME_SKIP 4
static int64_t assets_frame_counter = 1; static int64_t assets_frame_counter = 1;
static double assets_frame_next_draw = 0.0; static double assets_frame_next_draw = 0.0;
#include <time.h> #include <time.h>
static uint16_t asset_counter;
void assets_new(const char *name) {
assert(asset_counter < MAX_ASSETS);
db_exec(zpl_bprintf("INSERT INTO assets (id, name) VALUES (%d, '%s');", asset_counter++, name));
}
void assets_db_init(void) {
for (uint16_t i=0; i<MAX_INTERNAL_ASSETS; i++) {
assets_new(asset_names[i]+6);
}
asset_counter = NEXT_FREE_ASSET;
}
void assets_db(void) {
zpl_array_init(assets, zpl_heap());
db_push("SELECT * FROM resources;");
for (size_t i=0, end=db_rows(); i<end; i++) {
asset a={0};
a.id = db_int("asset", i);
a.kind = db_int("kind", i);
zpl_array_append(assets, a);
}
db_pop();
}
int32_t assets_setup(void) { int32_t assets_setup(void) {
for (uint32_t i=0; i<ASSETS_COUNT; i++) { for (uint32_t i=0; i<ASSETS_COUNT; i++) {
asset *b = &assets[i]; asset *b = &assets[i];
switch (b->kind) { switch (b->kind) {
case AKIND_TEXTURE: { case AKIND_TEXTURE: {
b->tex = texgen_build_sprite(b->id); b->tex = texgen_build_sprite(b->id);
}break; }break;
case AKIND_ANIM: { case AKIND_ANIM: {
b->tex = texgen_build_anim(b->id, 0); b->tex = texgen_build_anim(b->id, 0);
}break; }break;
case AKIND_SOUND: { case AKIND_SOUND: {
// TODO(zaklaus): soundgen // TODO(zaklaus): soundgen
}break; }break;
default: break; default: break;
} }
} }
@ -85,21 +53,21 @@ int32_t assets_frame(void) {
if (assets_frame_next_draw < get_cached_time()) { if (assets_frame_next_draw < get_cached_time()) {
for (uint32_t i=0; i<ASSETS_COUNT; i++) { for (uint32_t i=0; i<ASSETS_COUNT; i++) {
asset *b = &assets[i]; asset *b = &assets[i];
switch (b->kind) { switch (b->kind) {
case AKIND_ANIM: { case AKIND_ANIM: {
UnloadTexture(b->tex); UnloadTexture(b->tex);
b->tex = texgen_build_anim(b->id, assets_frame_counter); b->tex = texgen_build_anim(b->id, assets_frame_counter);
}break; }break;
default: break; default: break;
} }
} }
assets_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS; assets_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
assets_frame_counter += ASSET_FRAME_SKIP; assets_frame_counter += ASSET_FRAME_SKIP;
} }
return 0; return 0;
} }
@ -110,11 +78,11 @@ void assets_destroy(void) {
case AKIND_TEXTURE: { case AKIND_TEXTURE: {
UnloadTexture(assets[i].tex); UnloadTexture(assets[i].tex);
}break; }break;
case AKIND_SOUND: { case AKIND_SOUND: {
// TODO(zaklaus): soundgen // TODO(zaklaus): soundgen
}break; }break;
default: break; default: break;
} }
} }
@ -125,8 +93,8 @@ uint16_t assets_find(asset_id id) {
if (assets[i].id == id) if (assets[i].id == id)
return i; return i;
} }
//ZPL_PANIC("Unknown asset id: %d\n", id); ZPL_PANIC("Unknown asset id: %d\n", id);
return ASSET_INVALID; return ASSET_INVALID;
} }
@ -134,11 +102,6 @@ asset_kind assets_get_kind(uint16_t id) {
return assets[id].kind; return assets[id].kind;
} }
const char* assets_get_kind_name(uint16_t id) {
static const char* names[] = { "Texture", "Animated Texture", "Sound" };
return names[assets[id].kind];
}
void *assets_get_snd(uint16_t id) { void *assets_get_snd(uint16_t id) {
return (void*)&assets[id].snd;; return (void*)&assets[id].snd;;
} }
@ -146,9 +109,3 @@ void *assets_get_snd(uint16_t id) {
void *assets_get_tex(uint16_t id) { void *assets_get_tex(uint16_t id) {
return (void*)&assets[id].tex; return (void*)&assets[id].tex;
} }
const char *asset_names[] = {
#define X(id) #id,
_ASSETS
#undef X
};

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "platform/system.h" #include "platform/system.h"
#include "assets_ids.h" #include "lists/assets_ids.h"
typedef enum { typedef enum {
AKIND_TEXTURE, AKIND_TEXTURE,
@ -11,9 +11,6 @@ typedef enum {
FORCE_AKIND_UINT8 = UINT8_MAX FORCE_AKIND_UINT8 = UINT8_MAX
} asset_kind; } asset_kind;
void assets_db_init(void);
void assets_db(void);
void assets_new(const char *name);
int32_t assets_setup(void); int32_t assets_setup(void);
int32_t assets_frame(void); int32_t assets_frame(void);
void assets_destroy(void); void assets_destroy(void);
@ -21,13 +18,9 @@ void assets_destroy(void);
uint16_t assets_find(asset_id id); uint16_t assets_find(asset_id id);
asset_kind assets_get_kind(uint16_t id); asset_kind assets_get_kind(uint16_t id);
const char *assets_get_kind_name(uint16_t id);
void *assets_get_snd(uint16_t id); void *assets_get_snd(uint16_t id);
void *assets_get_tex(uint16_t id); void *assets_get_tex(uint16_t id);
uint16_t assets_resolve_proxy(uint16_t id);
// NOTE(zaklaus): client only // NOTE(zaklaus): client only
#define ASSET_SRC_RECT() ((Rectangle){0, 0, 64, 64}) #define ASSET_SRC_RECT() ((Rectangle){0, 0, 64, 64})
#define ASSET_DST_RECT(x,y) ((Rectangle){x, y, 64, 64}) #define ASSET_DST_RECT(x,y) ((Rectangle){x, y, 64, 64})
#define ASSET_SRC_RECT_TEX(w,h) ((Rectangle){0, 0, (float)w, (float)h})
#define ASSET_DST_RECT_TEX(x,y,w,h) ((Rectangle){x, y, (float)w, (float)h})

View File

@ -1,15 +1,51 @@
#include "models/components.h" #include "models/components.h"
ECS_COMPONENT_DECLARE(Vector2D);
ECS_COMPONENT_DECLARE(Position);
#define X(comp) ECS_COMPONENT_DECLARE(comp); ECS_COMPONENT_DECLARE(Velocity);
_COMPS ECS_COMPONENT_DECLARE(Chunk);
#undef X ECS_COMPONENT_DECLARE(Drawable);
ECS_COMPONENT_DECLARE(Input);
ECS_COMPONENT_DECLARE(ClientInfo);
ECS_COMPONENT_DECLARE(Health);
ECS_COMPONENT_DECLARE(Classify);
ECS_COMPONENT_DECLARE(Vehicle);
ECS_COMPONENT_DECLARE(IsInVehicle);
ECS_COMPONENT_DECLARE(Item);
ECS_COMPONENT_DECLARE(BlockHarvest);
ECS_COMPONENT_DECLARE(Inventory);
ECS_COMPONENT_DECLARE(ItemContainer);
ECS_COMPONENT_DECLARE(Producer);
ECS_COMPONENT_DECLARE(EnergySource);
ECS_COMPONENT_DECLARE(Ingredient);
ECS_COMPONENT_DECLARE(Device);
ECS_COMPONENT_DECLARE(Blueprint);
ECS_COMPONENT_DECLARE(DemoNPC);
ECS_COMPONENT_DECLARE(StreamInfo);
void ComponentsImport(ecs_world_t *ecs) { void ComponentsImport(ecs_world_t *ecs) {
ECS_MODULE(ecs, Components); ECS_MODULE(ecs, Components);
#define X(comp) ECS_COMPONENT_DEFINE(ecs, comp); ECS_COMPONENT_DEFINE(ecs, Vector2D);
_COMPS ECS_COMPONENT_DEFINE(ecs, Position);
#undef X ECS_COMPONENT_DEFINE(ecs, Velocity);
ECS_COMPONENT_DEFINE(ecs, Chunk);
ECS_COMPONENT_DEFINE(ecs, Drawable);
ECS_COMPONENT_DEFINE(ecs, Input);
ECS_COMPONENT_DEFINE(ecs, ClientInfo);
ECS_COMPONENT_DEFINE(ecs, Health);
ECS_COMPONENT_DEFINE(ecs, Classify);
ECS_COMPONENT_DEFINE(ecs, Vehicle);
ECS_COMPONENT_DEFINE(ecs, IsInVehicle);
ECS_COMPONENT_DEFINE(ecs, Item);
ECS_COMPONENT_DEFINE(ecs, BlockHarvest);
ECS_COMPONENT_DEFINE(ecs, Inventory);
ECS_COMPONENT_DEFINE(ecs, ItemContainer);
ECS_COMPONENT_DEFINE(ecs, Producer);
ECS_COMPONENT_DEFINE(ecs, EnergySource);
ECS_COMPONENT_DEFINE(ecs, Ingredient);
ECS_COMPONENT_DEFINE(ecs, Device);
ECS_COMPONENT_DEFINE(ecs, Blueprint);
ECS_COMPONENT_DEFINE(ecs, DemoNPC);
ECS_COMPONENT_DEFINE(ecs, StreamInfo);
} }

View File

@ -2,11 +2,19 @@
#include "flecs.h" #include "flecs.h"
#include "models/assets.h" #include "models/assets.h"
#define ecs_get_if(world, entity, T) \ #define ecs_get_mut_ex(world, entity, T) \
(world_entity_valid(entity) ? ecs_get(world, entity, T) : NULL) (ECS_CAST(T*, world_component_cached(world, entity, ecs_id(T))))
#define ecs_get_mut_if(world, entity, component) \ #define ecs_get_if(world, entity, T) \
(ecs_get_if(world, entity, component) ? ecs_get_mut(world, entity, component) : NULL) (world_entity_valid(entity) ? ecs_get(world, entity, T) : NULL)
#define ecs_get_mut_if_ex(world, entity, component) \
(ecs_get_if(world, entity, component) ? ecs_get_mut_ex(world, entity, component) : NULL)
#ifndef ecs_get_mut_if
#define ecs_get_mut_if(world, entity, component)\
(ecs_get(world, entity, component) ? ecs_get_mut(world, entity, component) : NULL)
#endif
#define ITEMS_INVENTORY_SIZE 9 #define ITEMS_INVENTORY_SIZE 9
#define ITEMS_CONTAINER_SIZE 16 #define ITEMS_CONTAINER_SIZE 16
@ -30,30 +38,6 @@ typedef struct {
typedef Vector2D Position; typedef Vector2D Position;
typedef Vector2D Velocity; typedef Vector2D Velocity;
typedef struct { char _unused; } InAir;
typedef struct { char _unused; } TriggerOnly;
typedef struct {
float angle;
} Rotation;
enum {
PHYS_CIRCLE,
PHYS_AABB,
};
#define INFINITE_MASS -1.0f
typedef struct {
uint8_t kind;
union {
struct {
float r;
} circle;
};
float mass;
} PhysicsBody;
typedef struct { typedef struct {
float x; float x;
float y; float y;
@ -61,8 +45,6 @@ typedef struct {
float my; float my;
float bx; float bx;
float by; float by;
float hx;
float hy;
uint8_t use; uint8_t use;
uint8_t sprint; uint8_t sprint;
uint8_t ctrl; uint8_t ctrl;
@ -70,7 +52,7 @@ typedef struct {
uint8_t is_blocked; uint8_t is_blocked;
ecs_entity_t pick_ent; ecs_entity_t pick_ent;
ecs_entity_t sel_ent; ecs_entity_t sel_ent;
// NOTE(zaklaus): inventory // NOTE(zaklaus): inventory
ecs_entity_t storage_ent; ecs_entity_t storage_ent;
uint8_t storage_action; uint8_t storage_action;
@ -81,8 +63,7 @@ typedef struct {
uint8_t swap_storage; uint8_t swap_storage;
uint8_t swap_from; uint8_t swap_from;
uint8_t swap_to; uint8_t swap_to;
asset_id craft_item;
// NOTE(zaklaus): build mode // NOTE(zaklaus): build mode
uint8_t num_placements; uint8_t num_placements;
float placements_x[20]; float placements_x[20];
@ -100,40 +81,23 @@ typedef struct {
float hp; float hp;
float max_hp; float max_hp;
// acumulated damage //NOTE(zaklaus): Intentionally global, to allow for creative use of damage combos
float dmg; float pain_time;
float heal_time;
} Health; } Health;
typedef struct { char _unused; } Dead;
typedef struct {
uint16_t timer;
} Respawn;
typedef struct {
float amt;
} HealthRegen;
typedef struct {
uint8_t delay;
} HealDelay;
typedef struct { typedef struct {
uint16_t id; uint16_t id;
} Classify; } Classify;
typedef struct {
uint8_t layer;
} StreamLayerOverride;
typedef struct { typedef struct {
uint64_t seats[4]; uint64_t seats[4];
float force; float force;
float heading; float heading;
float steer; float steer;
float wheel_base; float wheel_base;
float speed; float speed;
float reverse_speed; float reverse_speed;
uint8_t veh_kind; uint8_t veh_kind;
@ -150,19 +114,6 @@ typedef struct {
float durability; // 1.0 - 0.0 (0.0 = broken), we can only ever merge items of the same durability float durability; // 1.0 - 0.0 (0.0 = broken), we can only ever merge items of the same durability
} Item; } Item;
typedef struct {
union {
struct {
uint32_t spritesheet;
uint32_t frame;
};
struct {
uint32_t sprite_id;
uint32_t sprite_data;
};
};
} Sprite;
typedef struct { typedef struct {
char _unused; char _unused;
} BlockHarvest; } BlockHarvest;
@ -178,43 +129,26 @@ 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; float process_time;
int32_t process_ticks;
int32_t process_ticks_left;
float energy_level; float energy_level;
uint8_t pending_task;
uint8_t push_filter;
} Producer; } Producer;
typedef struct {
uint32_t push_qty;
uint8_t counter;
} ItemRouter;
typedef struct { typedef struct {
asset_id kind; asset_id kind;
float energy_level; float energy_level;
} EnergySource; } EnergySource;
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 { typedef struct {
uint16_t asset; uint16_t asset;
// progress bar // progress bar
uint8_t progress_active; uint8_t progress_active;
float progress_value; float progress_value;
@ -233,84 +167,27 @@ typedef struct {
typedef struct {char _unused;} DemoNPC; typedef struct {char _unused;} DemoNPC;
typedef struct { extern ECS_COMPONENT_DECLARE(Vector2D);
int16_t hunger_satisfied; extern ECS_COMPONENT_DECLARE(Position);
int16_t mating_satisfied; extern ECS_COMPONENT_DECLARE(Velocity);
int16_t life_remaining; extern ECS_COMPONENT_DECLARE(Chunk);
} Creature; extern ECS_COMPONENT_DECLARE(Drawable);
extern ECS_COMPONENT_DECLARE(Input);
typedef struct { char _unused; } SeeksFood; extern ECS_COMPONENT_DECLARE(ClientInfo);
typedef struct { char _unused; } SeeksCompanion; extern ECS_COMPONENT_DECLARE(Health);
extern ECS_COMPONENT_DECLARE(Classify);
// survival comps extern ECS_COMPONENT_DECLARE(Vehicle);
typedef struct { extern ECS_COMPONENT_DECLARE(IsInVehicle);
uint8_t atk_delay; extern ECS_COMPONENT_DECLARE(Item);
uint16_t despawn_timer; extern ECS_COMPONENT_DECLARE(BlockHarvest);
} Mob; extern ECS_COMPONENT_DECLARE(Inventory);
typedef struct { extern ECS_COMPONENT_DECLARE(ItemContainer);
uint64_t plr; extern ECS_COMPONENT_DECLARE(Producer);
} MobHuntPlayer; extern ECS_COMPONENT_DECLARE(EnergySource);
extern ECS_COMPONENT_DECLARE(Ingredient);
typedef struct { extern ECS_COMPONENT_DECLARE(Device);
char _unused; extern ECS_COMPONENT_DECLARE(Blueprint);
} MobMelee; extern ECS_COMPONENT_DECLARE(DemoNPC);
extern ECS_COMPONENT_DECLARE(StreamInfo);
typedef struct {
uint16_t projectile_count;
uint8_t damage;
uint8_t spawn_delay;
} WeaponKnife;
typedef struct {
uint8_t damage;
float origin_x, origin_y;
ecs_entity_t owner;
} WeaponProjectile;
#define _COMPS\
X(Vector2D)\
X(Position)\
X(Velocity)\
X(InAir)\
X(Rotation)\
X(TriggerOnly)\
X(PhysicsBody)\
X(Chunk)\
X(Drawable)\
X(Input)\
X(ClientInfo)\
X(Health)\
X(Dead)\
X(Respawn)\
X(HealthRegen)\
X(HealDelay)\
X(Mob)\
X(MobHuntPlayer)\
X(MobMelee)\
X(WeaponKnife)\
X(WeaponProjectile)\
X(Classify)\
X(Vehicle)\
X(StreamLayerOverride)\
X(IsInVehicle)\
X(Item)\
X(BlockHarvest)\
X(Inventory)\
X(ItemContainer)\
X(Producer)\
X(EnergySource)\
X(ItemRouter)\
X(Device)\
X(Blueprint)\
X(DemoNPC)\
X(Creature)\
X(SeeksFood)\
X(SeeksCompanion)\
X(Sprite)\
X(StreamInfo)
#define X(comp) extern ECS_COMPONENT_DECLARE(comp);
_COMPS
#undef X
void ComponentsImport(ecs_world_t *ecs); void ComponentsImport(ecs_world_t *ecs);

View File

@ -1,216 +0,0 @@
#include "crafting.h"
#include "models/items.h"
#include "models/database.h"
//#include "lists/crafting_list.c"
static recipe *recipes;
#define MAX_RECIPES (zpl_array_count(recipes))
void craft_db(void) {
zpl_array_init(recipes, zpl_heap());
db_push("SELECT * FROM recipes;");
for (size_t i=0, end=db_rows(); i<end; i++) {
recipe r={0};
r.product = db_int("product", i);
r.product_qty = db_int("product_qty", i);
r.process_ticks = db_int("process_ticks", i);
r.producer = db_int("producer", i);
zpl_array_init(r.reagents, zpl_heap());
db_push(zpl_bprintf("SELECT * FROM recipe_reagents WHERE recipe_id=%d;", i+1));
for (size_t j=0, j_end=db_rows(); j<j_end; j++) {
reagent rea={0};
size_t reagent_id = db_int("reagent_id", j);
db_push(zpl_bprintf("SELECT * FROM reagents WHERE id=%d;", reagent_id));
rea.id = db_int("asset_id", 0);
rea.qty = db_int("qty", 0);
db_pop();
zpl_array_append(r.reagents, rea);
}
db_pop();
zpl_array_append(recipes, r);
}
db_pop();
}
uint32_t craft__find_num_recipes_by_reagent(asset_id producer, asset_id id) {
uint32_t num_recipes=0;
for (int i = 0; i < (int)MAX_RECIPES; ++i) {
if (recipes[i].producer == producer) {
for (int j = 0; recipes[i].reagents[j].id; ++j) {
if (recipes[i].reagents[j].id == id) {
++num_recipes;
break;
}
}
}
}
return num_recipes;
}
recipe *craft__find_recipe_by_reagent(asset_id producer, asset_id id, uint32_t slot_id) {
for (int i = 0; i < (int)MAX_RECIPES; ++i) {
if (recipes[i].producer == producer) {
for (int j = 0; recipes[i].reagents[j].id; ++j) {
if (recipes[i].reagents[j].id == id) {
if (slot_id > 0) {
--slot_id;
continue;
}
return &recipes[i];
}
}
}
}
return NULL;
}
uint16_t craft_get_recipe_id_from_product(asset_id id) {
for (int i = 0; i < (int)MAX_RECIPES; ++i) {
if (id == recipes[i].product) {
return i;
}
}
return ASSET_INVALID;
}
recipe craft_get_recipe_data(uint16_t i) {
ZPL_ASSERT(i < MAX_RECIPES);
return recipes[i];
}
bool craft_is_reagent_used_in_producer(asset_id reagent, asset_id producer) {
return craft__find_num_recipes_by_reagent(producer, reagent) > 0;
}
bool craft_is_item_produced_by_producer(asset_id item, asset_id producer) {
for (int i = 0; i < (int)MAX_RECIPES; ++i) {
if (recipes[i].producer == producer && item == recipes[i].product) {
return true;
}
}
return false;
}
bool craft_is_item_produced_by_reagent(asset_id item, asset_id reagent) {
for (int i = 0; i < (int)MAX_RECIPES; ++i) {
if (item == recipes[i].product) {
for (int j = 0; recipes[i].reagents[j].id; ++j) {
if (recipes[i].reagents[j].id == reagent)
return true;
}
}
}
return false;
}
uint16_t craft_get_num_recipes(void) {
return MAX_RECIPES;
}
asset_id craft_get_recipe_asset(uint16_t id) {
ZPL_ASSERT(id < MAX_RECIPES);
return recipes[id].product;
}
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++) {
ecs_entity_t item_slot_ent = items[i];
if (item_slot_ent == 0) continue;
Item *item = item_get_data(item_slot_ent);
if (!item) continue;
uint32_t num_recipes = craft__find_num_recipes_by_reagent(producer, item->kind);
for (uint32_t rec_i = 0; rec_i < num_recipes; ++rec_i) {
// TODO(zaklaus): slow, find a better way to retrieve known recipes
recipe *rec = craft__find_recipe_by_reagent(producer, item->kind, rec_i);
if (!rec) {
// NOTE(zaklaus): this item is not used as a reagent, skip it.
// TODO(zaklaus): is this a bug? should we assert?
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;
// NOTE(zaklaus): analyse if all the reagents are present
for (int j = 0; rec->reagents[j].id; ++j) {
reagent *rea = &rec->reagents[j];
uint32_t pending_qty = rea->qty;
for (int k = 0; k < ITEMS_CONTAINER_SIZE; k++) {
ecs_entity_t rea_item_slot_ent = items[k];
if (rea_item_slot_ent == 0) continue;
Item *rea_item = item_get_data(rea_item_slot_ent);
if (!rea_item) continue;
if (rea->id == rea_item->kind && rea_item->quantity > 0) {
pending_qty -= zpl_min(pending_qty, rea_item->quantity);
if (pending_qty == 0) {
break;
}
}
}
if (pending_qty > 0) {
// NOTE(zaklaus): reagent not found, bail
skip_slot=1;
break;
}
}
// NOTE(zaklaus): demand not met, bye!
if (skip_slot)
continue;
// NOTE(zaklaus): deplete used reagents
for (int j = 0; rec->reagents[j].id; ++j) {
reagent *rea = &rec->reagents[j];
uint32_t pending_qty = rea->qty;
for (int k = 0; k < ITEMS_CONTAINER_SIZE; k++) {
ecs_entity_t rea_item_slot_ent = items[k];
if (rea_item_slot_ent == 0) continue;
Item *rea_item = item_get_data(rea_item_slot_ent);
if (!rea_item) continue;
if (rea->id == rea_item->kind && rea_item->quantity > 0) {
rea_item->quantity -= zpl_min(pending_qty, rea_item->quantity);
pending_qty -= zpl_min(pending_qty, rea_item->quantity);
if (rea_item->quantity == 0) {
item_despawn(rea_item_slot_ent);
items[k] = 0;
}
if (pending_qty == 0) {
break;
}
}
}
}
// NOTE(zaklaus): all done, return the product and its qty
*quantity = rec->product_qty;
*process_ticks = rec->process_ticks;
return rec->product;
}
}
return 0;
}
// TODO(zaklaus): might be removed
asset_id craft_has_byproducts(asset_id product) {
return 0xFF;
}
// TODO(zaklaus): might be removed
uint32_t craft_resolve_graph(asset_id product, uint16_t *hops, uint8_t direct_cost) {
return 0;
}

View File

@ -1,50 +0,0 @@
#pragma once
#include "platform/system.h"
#include "models/assets.h"
#include "models/components.h"
typedef struct {
asset_id id;
uint32_t qty;
} reagent;
typedef struct {
asset_id product;
uint32_t product_qty;
int32_t process_ticks;
asset_id producer;
reagent *reagents;
} recipe;
void craft_db(void);
// 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, 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);
// used to filter out craftables
bool craft_is_item_produced_by_producer(asset_id item, asset_id producer);
// used to filter out reagents
bool craft_is_item_produced_by_reagent(asset_id item, asset_id reagent);
// NOTE(zaklaus): utilities
uint16_t craft_get_num_recipes(void);
asset_id craft_get_recipe_asset(uint16_t id);
uint16_t craft_get_recipe_id_from_product(asset_id id);
recipe craft_get_recipe_data(uint16_t i);
//~TODO(zaklaus): not implemented and might get removed
// NOTE(zaklaus): informs us on whether this product has any byproducts desired.
asset_id craft_has_byproducts(asset_id product);
// NOTE(zaklaus): resolves the production chain and analyses the amount of items required
// and a number of hops (production layers) needed to produce the item.
// optionally, it allows to calculate "direct_cost" of the product.
uint32_t craft_resolve_graph(asset_id product, uint16_t *hops, uint8_t direct_cost);

View File

@ -1,191 +0,0 @@
#include "models/database.h"
#include "models/assets.h"
#include "3rd_sqlite3.h"
#include "zpl.h"
#include "world/blocks.h"
#include "models/crafting.h"
#include "models/items.h"
#ifndef ECO2D_DB
#define ECO2D_DB "eco2d.db"
#endif
static sqlite3 *db;
static zpl_array(zpl_csv_object) csv_stack;
static
void sql_asset(sqlite3_context *ctx, int argc, sqlite3_value **argv) {
if (argc == 1) {
const char *name = (const char *)sqlite3_value_text(argv[0]);
if (name) {
sqlite3_result_int(ctx, atoi(db_get(zpl_bprintf("SELECT id FROM assets WHERE name = '%s'", name), false)));
return;
}
}
sqlite3_result_null(ctx);
}
bool db_init() {
bool new_db = !zpl_fs_exists(ECO2D_DB);
sqlite3_open(ECO2D_DB, &db);
assert(db && "Failed to open database.");
zpl_array_init(csv_stack, zpl_heap());
sqlite3_create_function(db, "asset", 1, SQLITE_UTF8, NULL, sql_asset, NULL, NULL);
if (new_db) {
zpl_printf("[INFO] Creating new database...\n");
db_exec_file("art/queries/eco2d/tables.sql");
assets_db_init();
db_exec_file("art/queries/eco2d/resources.sql");
db_exec_file("art/queries/eco2d/blocks.sql");
db_exec_file("art/queries/eco2d/recipes.sql");
db_exec_file("art/queries/eco2d/items.sql");
}
// initialise models db
zpl_printf("[INFO] Loading models from database...\n");
assets_db(); zpl_printf("[INFO] Assets loaded.\n");
blocks_db(); zpl_printf("[INFO] Blocks loaded.\n");
craft_db(); zpl_printf("[INFO] Recipes loaded.\n");
item_db(); zpl_printf("[INFO] Items loaded.\n");
return new_db;
}
void db_shutdown() {
sqlite3_close(db);
}
char *db_get(char *query, bool header) {
sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, query, -1, &stmt, 0);
if (rc) {
zpl_printf("[ERROR] Failed to prepare query: %s\n", sqlite3_errmsg(db));
return 0;
}
zpl_string buf = zpl_string_make(zpl_heap(), "");
bool is_first=header;
int cols = sqlite3_column_count(stmt);
while (sqlite3_step(stmt) == SQLITE_ROW) {
if (is_first) {
is_first = 0;
for (int i = 0; i < cols; i++) {
buf = zpl_string_appendc(buf, (const char *)sqlite3_column_name(stmt, i));
if (i < cols - 1) {
buf = zpl_string_appendc(buf, ",");
}
}
buf = zpl_string_appendc(buf, "\n");
}
for (int i = 0; i < cols; i++) {
const char *val = (const char *)sqlite3_column_text(stmt, i);
if (val == NULL)
val = "\"(null)\"";
buf = zpl_string_appendc(buf, val);
if (i < cols - 1) {
buf = zpl_string_appendc(buf, ",");
}
}
buf = zpl_string_appendc(buf, "\n");
}
sqlite3_finalize(stmt);
#if 0
char *data = zpl_bprintf("%s", buf);
zpl_string_free(buf);
#else //@leak
char *data = (char *)buf;
#endif
return data;
}
char *db_row(char *table, char *name) {
int kind = atoi(db_get(zpl_bprintf("SELECT id FROM assets WHERE name='%s';", name), 0));
return db_get(zpl_bprintf("SELECT * FROM %s WHERE kind='%d';", table, kind), 1);
}
bool db_csv(zpl_csv_object *csv, char *query) {
zpl_zero_item(csv);
char *res = db_get(query, 1);
assert(res);
return zpl_csv_parse(csv, res, zpl_heap(), 1);
}
bool db_row_csv(zpl_csv_object *csv, char *table, char *name) {
zpl_zero_item(csv);
char *res = db_row(table, name);
assert(res);
return zpl_csv_parse(csv, res, zpl_heap(), 1);
}
bool db_push(char *query) {
zpl_csv_object csv;
if (db_csv(&csv, query)) {
return false;
}
zpl_array_append(csv_stack, csv);
return true;
}
bool db_row_push(char *table, char *name) {
zpl_csv_object csv;
if (db_row_csv(&csv, table, name)) {
return false;
}
zpl_array_append(csv_stack, csv);
return true;
}
zpl_adt_node *db_field(char *field, int row) {
zpl_csv_object *csv = db_last();
for (int i = 0; i < zpl_array_count(csv->nodes); i++) {
if (!zpl_strcmp(csv->nodes[i].name, field)) {
return &csv->nodes[i].nodes[row];
}
}
assert(0 && "Field not found");
return NULL;
}
size_t db_rows() {
zpl_csv_object *csv = db_last();
return zpl_array_count(csv->nodes[0].nodes);
}
zpl_csv_object *db_last() {
assert(zpl_array_count(csv_stack) > 0);
return zpl_array_end(csv_stack);
}
void db_pop() {
assert(zpl_array_count(csv_stack) > 0);
zpl_csv_free(zpl_array_end(csv_stack));
zpl_array_pop(csv_stack);
}
bool db_exec_file(const char *sql) {
zpl_file_contents contents = zpl_file_read_contents(zpl_heap(), true, sql);
if (!db_exec(contents.data)) {
assert(0 && "Failed to create tables");
return false;
}
zpl_file_free_contents(&contents);
return true;
}
bool db_exec(const char *query) {
bool ok = !sqlite3_exec(db, query, 0, 0, 0);
if (!ok) {
zpl_printf("[ERROR] Failed to execute query: %s\n", sqlite3_errmsg(db));
}
return ok;
}

View File

@ -1,28 +0,0 @@
#pragma once
#include "platform/system.h"
#include "zpl.h"
bool db_init();
void db_shutdown();
// raw query data getters
char *db_get(char *query, bool header);
char *db_row(char *table, char *name);
bool db_csv(zpl_csv_object *csv, char *query);
bool db_row_csv(zpl_csv_object *csv, char *table, char *name);
// csv backed data queries
bool db_push(char *query);
bool db_row_push(char *table, char *name);
zpl_adt_node *db_field(char *field, int row);
size_t db_rows();
#define db_str(fld, row) (db_field(fld, row)->string)
#define db_flt(fld, row) (db_field(fld, row)->type == ZPL_ADT_TYPE_STRING ? 0.0f : db_field(fld, row)->real)
#define db_int(fld, row) (db_field(fld, row)->type == ZPL_ADT_TYPE_STRING ? 0 : db_field(fld, row)->integer)
zpl_csv_object *db_last();
void db_pop();
// sql execution
bool db_exec_file(const char *sql);
bool db_exec(const char *query);

View File

@ -8,44 +8,8 @@
#include "systems/systems.h" #include "systems/systems.h"
#include "zpl.h" #include "zpl.h"
typedef struct {
asset_id id;
uint64_t (*proc)();
uint64_t (*proc_udata)(void*);
} spawndef;
static spawndef *entity_spawnlist;
void entity_add_spawndef(uint16_t id, uint64_t (*proc)()) {
spawndef def={0};
def.id = id;
def.proc = proc;
zpl_array_append(entity_spawnlist, def);
}
void entity_add_spawndef_data(uint16_t id, uint64_t (*proc)(void*)) {
spawndef def={0};
def.id = id;
def.proc_udata = proc;
zpl_array_append(entity_spawnlist, def);
}
// NOTE(zaklaus): bring in entity spawnlist // NOTE(zaklaus): bring in entity spawnlist
// #include "lists/entity_spawnlist.c" #include "lists/entity_spawnlist.c"
#include "models/prefabs/prefabs_list.c"
#define MAX_ENTITY_SPAWNDEFS ((size_t)zpl_array_count(entity_spawnlist))
void entity_default_spawnlist(void) {
zpl_array_init(entity_spawnlist, zpl_heap());
entity_add_spawndef(ASSET_CHEST, storage_spawn);
entity_add_spawndef(ASSET_FURNACE, furnace_spawn);
entity_add_spawndef(ASSET_CRAFTBENCH, craftbench_spawn);
entity_add_spawndef(ASSET_SPLITTER, splitter_spawn);
entity_add_spawndef(ASSET_ASSEMBLER, assembler_spawn);
entity_add_spawndef(ASSET_CREATURE, creature_spawn);
entity_add_spawndef_data(ASSET_BLUEPRINT, blueprint_spawn_udata);
}
uint64_t entity_spawn(uint16_t class_id) { uint64_t entity_spawn(uint16_t class_id) {
ecs_entity_t e = ecs_new(world_ecs(), 0); ecs_entity_t e = ecs_new(world_ecs(), 0);
@ -54,13 +18,20 @@ uint64_t entity_spawn(uint16_t class_id) {
entity_wake(e); entity_wake(e);
if (class_id != EKIND_SERVER) { if (class_id != EKIND_SERVER) {
librg_entity_track(world_tracker(), e); ecs_set(world_ecs(), e, Velocity, {0});
librg_entity_track(world_collision_grid(), e); Position *pos = ecs_get_mut(world_ecs(), e, Position);
ecs_set(world_ecs(), e, Velocity, { 0 }); #if 1
entity_set_position(e, (float)(rand() % world_dim()), (float)(rand() % world_dim())); pos->x=(float)(rand() % world_dim());
pos->y=(float)(rand() % world_dim());
entity_set_position(e, pos->x, pos->y);
#else
pos->x=350.0f;
pos->y=88.0f;
#endif
librg_entity_track(world_tracker(), e);
librg_entity_chunk_set(world_tracker(), e, librg_chunk_from_realpos(world_tracker(), pos->x, pos->y, 0));
librg_entity_owner_set(world_tracker(), e, (int64_t)e); librg_entity_owner_set(world_tracker(), e, (int64_t)e);
librg_entity_owner_set(world_collision_grid(), e, (int64_t)e);
} }
return (uint64_t)e; return (uint64_t)e;
@ -85,19 +56,8 @@ uint64_t entity_spawn_id_with_data(uint16_t id, void *udata){
} }
return 0; return 0;
} }
bool entity_spawn_provided(uint16_t id) {
for (size_t i = 0; i < MAX_ENTITY_SPAWNDEFS; ++i){
if (entity_spawnlist[i].id == id){
return true;
}
}
return false;
}
void entity_batch_despawn(uint64_t *ids, size_t num_ids) { void entity_batch_despawn(uint64_t *ids, size_t num_ids) {
for (size_t i = 0; i < num_ids; i++ ) { for (size_t i = 0; i < num_ids; i++ ) {
librg_entity_untrack(world_collision_grid(), ids[i]);
librg_entity_untrack(world_tracker(), ids[i]); librg_entity_untrack(world_tracker(), ids[i]);
ecs_delete(world_ecs(), ids[i]); ecs_delete(world_ecs(), ids[i]);
} }
@ -105,17 +65,14 @@ void entity_batch_despawn(uint64_t *ids, size_t num_ids) {
void entity_despawn(uint64_t ent_id) { void entity_despawn(uint64_t ent_id) {
librg_entity_untrack(world_tracker(), ent_id); librg_entity_untrack(world_tracker(), ent_id);
librg_entity_untrack(world_collision_grid(), ent_id);
ecs_delete(world_ecs(), ent_id); ecs_delete(world_ecs(), ent_id);
} }
void entity_set_position(uint64_t ent_id, float x, float y) { void entity_set_position(uint64_t ent_id, float x, float y) {
ecs_set(world_ecs(), ent_id, Position, {x, y});
Position *p = ecs_get_mut(world_ecs(), ent_id, Position); Position *p = ecs_get_mut(world_ecs(), ent_id, Position);
p->x = x; p->x = x;
p->y = y; p->y = y;
librg_entity_chunk_set(world_tracker(), ent_id, librg_chunk_from_realpos(world_tracker(), x, y, 0)); librg_entity_chunk_set(world_tracker(), ent_id, librg_chunk_from_realpos(world_tracker(), x, y, 0));
librg_entity_chunk_set(world_collision_grid(), ent_id, librg_chunk_from_realpos(world_collision_grid(), x, y, 0));
entity_wake(ent_id); entity_wake(ent_id);
} }

View File

@ -6,16 +6,10 @@
uint64_t entity_spawn(uint16_t class_id /* 0 = no streaming */); uint64_t entity_spawn(uint16_t class_id /* 0 = no streaming */);
uint64_t entity_spawn_id(uint16_t id); uint64_t entity_spawn_id(uint16_t id);
uint64_t entity_spawn_id_with_data(uint16_t id, void* udata); uint64_t entity_spawn_id_with_data(uint16_t id, void* udata);
bool entity_spawn_provided(uint16_t id);
void entity_batch_despawn(uint64_t *ids, size_t num_ids); void entity_batch_despawn(uint64_t *ids, size_t num_ids);
void entity_despawn(uint64_t ent_id); void entity_despawn(uint64_t ent_id);
void entity_set_position(uint64_t ent_id, float x, float y); void entity_set_position(uint64_t ent_id, float x, float y);
// NOTE(zaklaus): spawndef manager
void entity_add_spawndef(uint16_t id, uint64_t (*proc)());
void entity_add_spawndef_data(uint16_t id, uint64_t (*proc)(void*));
void entity_default_spawnlist(void);
// NOTE(zaklaus): action-based entity stream throttling // NOTE(zaklaus): action-based entity stream throttling
void entity_wake(uint64_t ent_id); void entity_wake(uint64_t ent_id);

View File

@ -3,72 +3,16 @@
#include "world/entity_view.h" #include "world/entity_view.h"
#include "world/world.h" #include "world/world.h"
#include "world/blocks.h" #include "world/blocks.h"
#include "models/database.h"
#include "models/components.h" #include "models/components.h"
#include "zpl.h" #include "zpl.h"
//#include "lists/items_list.c" #include "lists/items_list.c"
static item_desc *items; #define ITEMS_COUNT (sizeof(items)/sizeof(item_desc))
#define ITEMS_COUNT (zpl_array_count(items))
void item_db(void) {
zpl_array_init(items, zpl_heap());
db_push("SELECT * FROM items;");
for (size_t i = 0, end = db_rows(); i < end; i++) {
item_desc item = {0};
item.kind = db_int("kind", i);
item.usage = db_int("usage", i);
item.attachment = db_int("attachment", i);
item.max_quantity = db_int("max_quantity", i);
item.has_storage = db_int("has_storage", i);
switch (item.usage) {
case UKIND_PLACE:
case UKIND_PLACE_ITEM:
case UKIND_PLACE_ITEM_DATA:
item.place.kind = db_int("place_kind", i);
item.place.directional = db_int("directional", i);
item.place_item.id = db_int("place_item_id", i);
break;
case UKIND_PROXY:
item.proxy.id = db_int("proxy_id", i);
break;
default:
break;
}
switch (item.attachment) {
case UDATA_ENERGY_SOURCE:
item.energy_source.producer = db_int("producer", i);
item.energy_source.energy_level = db_flt("energy_level", i);
break;
default:
break;
}
// Handle blueprint data if present
// if (item.usage == UKIND_PLACE_ITEM_DATA) {
// item.blueprint.w = db_int("blueprint_w", i);
// item.blueprint.h = db_int("blueprint_h", i);
// const char *plan_str = db_str("blueprint_plan", i);
//
// // Convert the plan string to an array of asset_id
// size_t plan_len = strlen(plan_str);
// item.blueprint.plan = malloc(plan_len * sizeof(asset_id));
// for (size_t j = 0; j < plan_len; j++) {
// item.blueprint.plan[j] = plan_str[j]; // Assuming plan_str is a string of asset_id
// }
// }
zpl_array_append(items, item);
}
db_pop();
}
static inline item_id item_resolve_proxy(item_id id) { static inline item_id item_resolve_proxy(item_id id) {
ZPL_ASSERT(id < ITEMS_COUNT); ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
item_usage usage = items[id].usage; item_usage usage = items[id].usage;
if (usage == UKIND_PROXY) { if (usage == UKIND_PROXY) {
return item_find(items[id].proxy.id); return item_find(items[id].proxy.id);
@ -88,7 +32,7 @@ void item_show(uint64_t ent, bool show) {
uint64_t item_spawn(asset_id kind, uint32_t qty) { uint64_t item_spawn(asset_id kind, uint32_t qty) {
ecs_entity_t e = entity_spawn(EKIND_ITEM); ecs_entity_t e = entity_spawn(EKIND_ITEM);
Item *d = ecs_get_mut(world_ecs(), e, Item); Item *d = ecs_get_mut(world_ecs(), e, Item);
*d = (Item){ *d = (Item){
.kind = item_fix_kind(kind), .kind = item_fix_kind(kind),
@ -96,26 +40,32 @@ uint64_t item_spawn(asset_id kind, uint32_t qty) {
.merger_time = 0, .merger_time = 0,
.durability = 1.0f, .durability = 1.0f,
}; };
item_desc *it = &items[item_find(kind)]; item_desc *it = &items[item_find(kind)];
if (it->has_storage) { if (it->has_storage) {
ecs_add(world_ecs(), e, BlockHarvest); ecs_add(world_ecs(), e, BlockHarvest);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer); ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0}; *storage = (ItemContainer){0};
} }
switch (it->attachment) { switch (it->attachment) {
case UDATA_ENERGY_SOURCE: { case UDATA_ENERGY_SOURCE: {
EnergySource *f = ecs_get_mut(world_ecs(), e, EnergySource); EnergySource *f = ecs_get_mut(world_ecs(), e, EnergySource);
*f = (EnergySource){ *f = (EnergySource){
.kind = it->energy_source.producer, .kind = it->energy_source.producer,
.energy_level = it->energy_source.energy_level, .energy_level = it->energy_source.energy_level,
}; };
} break; } break;
default: 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; return (uint64_t)e;
} }
@ -127,17 +77,11 @@ item_id item_find(asset_id kind) {
return ASSET_INVALID; return ASSET_INVALID;
} }
item_id item_find_no_proxy(asset_id kind) {
for (item_id i=0; i<ITEMS_COUNT; i++) {
if (items[i].kind == kind)
return i;
}
return ASSET_INVALID;
}
Item *item_get_data(uint64_t ent) { Item *item_get_data(uint64_t ent) {
if (!world_entity_valid(ent)) return NULL; if (!world_entity_valid(ent)) return NULL;
return ecs_get_mut_if(world_ecs(), ent, Item); // if (ecs_get(world_ecs(), ent, ItemAlreadyEdited)) return NULL;
// ecs_add(world_ecs(), ent, ItemAlreadyEdited);
return ecs_get_mut_if_ex(world_ecs(), ent, Item);
} }
const Item *item_get_data_const(uint64_t ent) { const Item *item_get_data_const(uint64_t ent) {
@ -158,7 +102,7 @@ void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t u
asset_id item_asset = blocks_get_asset(l.bid); asset_id item_asset = blocks_get_asset(l.bid);
item_id item_asset_id = item_find(item_asset); item_id item_asset_id = item_find(item_asset);
if (item_asset_id == ASSET_INVALID) return; if (item_asset_id == ASSET_INVALID) return;
// NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it // NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it
if (item_asset_id == it_id) { if (item_asset_id == it_id) {
it->quantity++; it->quantity++;
@ -173,7 +117,7 @@ void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t u
world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata)); world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata));
it->quantity--; it->quantity--;
}break; }break;
case UKIND_PLACE_ITEM:{ case UKIND_PLACE_ITEM:{
world_block_lookup l = world_block_from_realpos(p.x, p.y); world_block_lookup l = world_block_from_realpos(p.x, p.y);
if (l.is_outer && l.bid > 0) { if (l.is_outer && l.bid > 0) {
@ -183,14 +127,14 @@ void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t u
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) { else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
return; return;
} }
ecs_entity_t e = entity_spawn_id(desc->place_item.id); ecs_entity_t e = entity_spawn_id(desc->place_item.id);
ZPL_ASSERT(world_entity_valid(e)); ZPL_ASSERT(world_entity_valid(e));
entity_set_position(e, p.x, p.y); entity_set_position(e, p.x, p.y);
it->quantity--; it->quantity--;
}break; }break;
case UKIND_PLACE_ITEM_DATA:{ case UKIND_PLACE_ITEM_DATA:{
world_block_lookup l = world_block_from_realpos(p.x, p.y); world_block_lookup l = world_block_from_realpos(p.x, p.y);
if (l.is_outer && l.bid > 0) { if (l.is_outer && l.bid > 0) {
@ -200,14 +144,14 @@ void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t u
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) { else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
return; return;
} }
ecs_entity_t e = entity_spawn_id_with_data(desc->place_item.id, desc); ecs_entity_t e = entity_spawn_id_with_data(desc->place_item.id, desc);
ZPL_ASSERT(world_entity_valid(e)); ZPL_ASSERT(world_entity_valid(e));
entity_set_position(e, p.x, p.y); entity_set_position(e, p.x, p.y);
it->quantity--; it->quantity--;
}break; }break;
case UKIND_DELETE: case UKIND_DELETE:
case UKIND_END_PLACE: case UKIND_END_PLACE:
case UKIND_PROXY: case UKIND_PROXY:
@ -220,21 +164,16 @@ void item_despawn(uint64_t id) {
} }
uint32_t item_max_quantity(item_id id) { uint32_t item_max_quantity(item_id id) {
ZPL_ASSERT(id < ITEMS_COUNT); ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
return items[id].max_quantity; return items[id].max_quantity;
} }
item_usage item_get_usage(item_id id) { item_usage item_get_usage(item_id id) {
ZPL_ASSERT(id < ITEMS_COUNT); ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
return items[id].usage; return items[id].usage;
} }
bool item_get_place_directional(item_id id) { bool item_get_place_directional(item_id id) {
ZPL_ASSERT(id < ITEMS_COUNT); ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
return items[id].place.directional; return items[id].place.directional;
} }
item_desc item_get_desc(item_id id) {
ZPL_ASSERT(id < ITEMS_COUNT);
return items[id];
}

View File

@ -12,7 +12,7 @@ typedef enum {
UKIND_PLACE_ITEM, UKIND_PLACE_ITEM,
UKIND_PLACE_ITEM_DATA, UKIND_PLACE_ITEM_DATA,
UKIND_END_PLACE, UKIND_END_PLACE,
// NOTE(zaklaus): the rest of possible actions // NOTE(zaklaus): the rest of possible actions
UKIND_HOLD, UKIND_HOLD,
UKIND_PROXY, UKIND_PROXY,
@ -21,6 +21,7 @@ typedef enum {
typedef enum { typedef enum {
UDATA_NONE, UDATA_NONE,
UDATA_ENERGY_SOURCE, UDATA_ENERGY_SOURCE,
UDATA_INGREDIENT,
} item_attachment; } item_attachment;
typedef struct { typedef struct {
@ -29,30 +30,36 @@ typedef struct {
item_attachment attachment; item_attachment attachment;
uint32_t max_quantity; uint32_t max_quantity;
uint8_t has_storage; uint8_t has_storage;
// NOTE(zaklaus): usage data // NOTE(zaklaus): usage data
union { union {
struct { struct {
asset_id kind; asset_id kind;
bool directional; // NOTE(zaklaus): expects next 4 asset entries to be direction assets bool directional; // NOTE(zaklaus): expects next 4 asset entries to be direction assets
} place; } place;
struct { struct {
asset_id id; asset_id id;
} proxy; } proxy;
struct { struct {
asset_id id; asset_id id;
} place_item; } place_item;
}; };
union { union {
struct { struct {
asset_id producer; asset_id producer;
float energy_level; float energy_level;
} energy_source; } energy_source;
struct {
asset_id producer;
asset_id product;
asset_id additional_ingredient;
} ingredient;
}; };
// NOTE: item data // NOTE: item data
union { union {
struct { struct {
@ -65,8 +72,6 @@ typedef struct {
typedef uint16_t item_id; typedef uint16_t item_id;
void item_db(void);
// NOTE(zaklaus): item drops // NOTE(zaklaus): item drops
void item_show(uint64_t ent, bool show); void item_show(uint64_t ent, bool show);
@ -75,7 +80,6 @@ void item_despawn(uint64_t id);
// NOTE(zaklaus): items // NOTE(zaklaus): items
item_id item_find(asset_id kind); item_id item_find(asset_id kind);
item_id item_find_no_proxy(asset_id kind);
void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *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); Item *item_get_data(uint64_t ent);
const Item *item_get_data_const(uint64_t ent); const Item *item_get_data_const(uint64_t ent);
@ -83,4 +87,3 @@ const Item *item_get_data_const(uint64_t ent);
uint32_t item_max_quantity(item_id id); uint32_t item_max_quantity(item_id id);
item_usage item_get_usage(item_id id); item_usage item_get_usage(item_id id);
bool item_get_place_directional(item_id id); bool item_get_place_directional(item_id id);
item_desc item_get_desc(item_id id);

View File

@ -0,0 +1,30 @@
#include "vehicle.h"
#include "world/entity_view.h"
#include "world/world.h"
#include "models/device.h"
#include "models/entity.h"
#include "models/items.h"
#include "models/components.h"
uint64_t blueprint_spawn(uint8_t w, uint8_t h, const asset_id *plan) {
ZPL_ASSERT((w*h) < 256);
ecs_entity_t e = device_spawn(ASSET_BLUEPRINT);
Blueprint *blueprint = ecs_get_mut(world_ecs(), e, Blueprint);
blueprint->w = w;
blueprint->h = h;
zpl_memcopy(blueprint->plan, plan, w*h*sizeof(asset_id));
return (uint64_t)e;
}
uint64_t blueprint_spawn_udata(void* udata) {
item_desc *it = (item_desc*)udata;
return blueprint_spawn(it->blueprint.w, it->blueprint.h, it->blueprint.plan);
}
void blueprint_despawn(uint64_t id) {
entity_despawn(id);
}

View File

@ -0,0 +1,8 @@
#pragma once
#include "platform/system.h"
uint64_t blueprint_spawn(uint8_t w, uint8_t h, const uint16_t *plan);
uint64_t blueprint_spawn_udata(void* udata);
void blueprint_despawn(uint64_t id);

View File

@ -0,0 +1,22 @@
#include "furnace.h"
#include "models/device.h"
#include "world/world.h"
#include "models/entity.h"
#include "models/components.h"
uint64_t furnace_spawn(void) {
ecs_entity_t e = device_spawn(ASSET_FURNACE);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0};
Producer *producer = ecs_get_mut(world_ecs(), e, Producer);
*producer = (Producer){0};
producer->energy_level = 69.0f;
return (uint64_t)e;
}
void furnace_despawn(uint64_t ent_id) {
entity_despawn(ent_id);
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "platform/system.h"
uint64_t furnace_spawn(void);
void furnace_despawn(uint64_t id);

View File

@ -6,8 +6,6 @@
#include "models/entity.h" #include "models/entity.h"
#include "models/components.h" #include "models/components.h"
#include "core/game.h"
#define PLAYER_MAX_HP 100.0f #define PLAYER_MAX_HP 100.0f
uint64_t player_spawn(char *name) { uint64_t player_spawn(char *name) {
@ -19,12 +17,9 @@ 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, Health, {.hp = PLAYER_MAX_HP, .max_hp = PLAYER_MAX_HP}); ecs_set(world_ecs(), e, Input, {0});
ecs_set(world_ecs(), e, Velocity, { 0 }); ecs_set(world_ecs(), e, Inventory, {0});
ecs_set(world_ecs(), e, PhysicsBody, { .kind = PHYS_AABB, .mass = INFINITE_MASS }); ecs_set(world_ecs(), e, Health, {.hp = PLAYER_MAX_HP, .max_hp = PLAYER_MAX_HP});
Input *i = ecs_get_mut(world_ecs(), e, Input);
*i = (Input){ 0 };
i->hx = 1.0f;
librg_entity_owner_set(world_tracker(), e, (int64_t)e); librg_entity_owner_set(world_tracker(), e, (int64_t)e);
@ -32,6 +27,5 @@ uint64_t player_spawn(char *name) {
} }
void player_despawn(uint64_t ent_id) { void player_despawn(uint64_t ent_id) {
game_player_departed(ent_id);
entity_despawn(ent_id); entity_despawn(ent_id);
} }

View File

@ -1,120 +0,0 @@
#include "models/device.h"
#include "models/assets.h"
#include "world/world.h"
#include "models/components.h"
#include "world/entity_view.h"
#include "world/world.h"
#include "models/device.h"
#include "models/entity.h"
#include "models/items.h"
#include "models/components.h"
//------------------------------------------------------------------------
uint64_t assembler_spawn(void) {
ecs_entity_t e = device_spawn(ASSET_ASSEMBLER);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0};
Producer *producer = ecs_get_mut(world_ecs(), e, Producer);
*producer = (Producer){0};
producer->energy_level = 69.0f;
producer->pending_task = PRODUCER_CRAFT_AUTO;
producer->push_filter = PRODUCER_PUSH_PRODUCT;
producer->target_item = ASSET_INVALID;
ecs_set(world_ecs(), e, ItemRouter, {.push_qty = 1, .counter = 0});
return (uint64_t)e;
}
//------------------------------------------------------------------------
uint64_t blueprint_spawn(uint8_t w, uint8_t h, const asset_id *plan) {
ZPL_ASSERT((w*h) < 256);
ecs_entity_t e = device_spawn(ASSET_BLUEPRINT);
Blueprint *blueprint = ecs_get_mut(world_ecs(), e, Blueprint);
blueprint->w = w;
blueprint->h = h;
zpl_memcopy(blueprint->plan, plan, w*h*sizeof(asset_id));
return (uint64_t)e;
}
uint64_t blueprint_spawn_udata(void* udata) {
item_desc *it = (item_desc*)udata;
return blueprint_spawn(it->blueprint.w, it->blueprint.h, it->blueprint.plan);
}
//------------------------------------------------------------------------
uint64_t craftbench_spawn(void) {
ecs_entity_t e = device_spawn(ASSET_CRAFTBENCH);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0};
Producer *producer = ecs_get_mut(world_ecs(), e, Producer);
*producer = (Producer){0};
producer->energy_level = 69.0f;
producer->pending_task = PRODUCER_CRAFT_WAITING;
producer->push_filter = PRODUCER_PUSH_NONE;
return (uint64_t)e;
}
//------------------------------------------------------------------------
uint64_t creature_spawn(void) {
ecs_entity_t e = entity_spawn(EKIND_DEMO_NPC);
Creature *c = ecs_get_mut(world_ecs(), e, Creature);
c->hunger_satisfied = 0;
c->mating_satisfied = rand() % 1800;
c->life_remaining = 500 + rand() % 5200;
return (uint64_t)e;
}
//------------------------------------------------------------------------
uint64_t furnace_spawn(void) {
ecs_entity_t e = device_spawn(ASSET_FURNACE);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0};
Producer *producer = ecs_get_mut(world_ecs(), e, Producer);
*producer = (Producer){0};
producer->energy_level = 69.0f;
producer->pending_task = PRODUCER_CRAFT_AUTO;
producer->push_filter = PRODUCER_PUSH_ANY;
ecs_set(world_ecs(), e, ItemRouter, {.push_qty = 1, .counter = 0});
return (uint64_t)e;
}
//------------------------------------------------------------------------
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, {.push_qty = 1, .counter = 0});
return (uint64_t)e;
}
//------------------------------------------------------------------------
uint64_t storage_spawn(void) {
ecs_entity_t e = device_spawn(ASSET_CHEST);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0};
return (uint64_t)e;
}
//------------------------------------------------------------------------

View File

@ -0,0 +1,18 @@
#include "storage.h"
#include "models/device.h"
#include "world/world.h"
#include "models/entity.h"
#include "models/components.h"
uint64_t storage_spawn(void) {
ecs_entity_t e = device_spawn(ASSET_CHEST);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0};
return (uint64_t)e;
}
void storage_despawn(uint64_t ent_id) {
entity_despawn(ent_id);
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "platform/system.h"
uint64_t storage_spawn(void);
void storage_despawn(uint64_t id);

Some files were not shown because too many files have changed in this diff Show More