Compare commits

..

127 Commits

Author SHA1 Message Date
Dominik Madarász 2d593809d7 move queries 2024-05-29 17:50:42 +02:00
Dominik Madarász 23645ed32a move ASSET_MOB to survival game 2024-05-29 11:18:48 +02:00
Dominik Madarász 29d9b9306d drop lists dir 2024-05-29 11:10:44 +02:00
Dominik Madarász 6e09c09037 style 2024-05-29 10:58:16 +02:00
Dominik Madarász b348400c1a streamline assets= 2024-05-29 10:45:43 +02:00
Dominik Madarász a9ea1e9335 sqlite db 2024-05-29 10:11:37 +02:00
Dominik Madarász e2e6ef9185 Update README.md 2023-09-16 06:57:33 +00:00
Dominik Madarász 3fba1bc1d4 collision grid + perf improvements 2023-07-27 11:53:35 +02:00
Dominik Madarász e43b167435 rename prj 2023-07-26 19:08:34 +02:00
Dominik Madarász a9efa0f01c big chungus 2023-07-26 19:05:50 +02:00
Dominik Madarász 213710e922 mob spawner + friendly fire 2023-07-26 14:53:50 +02:00
Dominik Madarász d864661e65 render mobs via spritesheet + blood splatters 2023-07-25 22:18:19 +02:00
Dominik Madarász 9c669407fc fix long-standing web build time related bug 2023-07-25 21:23:41 +02:00
Dominik Madarász a1d576fe8a update flecs 2023-06-30 15:14:47 +02:00
Dominik Madarász 200d0a1e6d remove flecs-dash 2023-06-30 15:04:20 +02:00
Dominik Madarász 00f0a672f8 optimize IntegratePositions system to avoid comp fetch + update flecs v3.2.3 2023-06-07 09:52:08 +02:00
Dominik Madarász 4a07e4ff4c allow entities to override stream layer 2023-02-28 09:11:33 +01:00
Dominik Madarász c022b104d0 drop world_component_cache 2023-02-28 09:11:27 +01:00
Dominik Madarász a9898527ee dropped component caching
This was fixed in flecs already
2023-02-13 10:31:08 +01:00
Dominik Madarász e302d1c865 bunch of code quality fixes 2023-02-10 06:42:30 +01:00
Dominik Madarász eccaa14bda improve player init 2023-02-03 11:22:15 +01:00
Dominik Madarász 94c49e770b add pkt_send_code + system changes 2023-02-03 09:54:16 +01:00
Dominik Madarász 3e4814222e improve force feedback 2023-02-03 07:31:36 +01:00
Dominik Madarász 410d6e5f11 set up dmg system for mobs 2023-02-03 07:28:17 +01:00
DavoSK cf200e8bf5 weapon hit system 2023-02-02 22:01:03 +01:00
DavoSK ea9b201a08 proper pos offset 2023-02-02 19:22:12 +01:00
DavoSK c21cb39140 implemented angles in sprite rendering, knifes has proper rotation based from direction of player 2023-02-02 18:59:49 +01:00
DavoSK 3a9196d19a adjust starting pos of projectile based on direction 2023-02-02 18:52:11 +01:00
DavoSK 98b9f3431e random offseting of knifes 2023-02-02 17:49:29 +01:00
Dominik Madarász d15e7da7cc again 2023-02-02 17:29:39 +01:00
DavoSK 7356168b6f player is shooting knifes now 2023-02-02 17:28:15 +01:00
DavoSK 1631e9199b Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 17:27:17 +01:00
Dominik Madarász 7ed35706fc fix heading dir 2023-02-02 17:26:33 +01:00
DavoSK e89cd75388 Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 17:23:21 +01:00
DavoSK f89b35a856 Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 17:22:07 +01:00
Dominik Madarász 8c288dc193 add heading dir to input 2023-02-02 17:22:05 +01:00
Dominik Madarász fc9997d4db Add rotation component 2023-02-02 16:58:20 +01:00
DavoSK 5473ca3c46 Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 16:55:51 +01:00
DavoSK 698d3d2089 projectile work 2023-02-02 16:55:49 +01:00
Dominik Madarász 78c05fd9da Add collision masking tags 2023-02-02 16:54:32 +01:00
DavoSK f6d5c76d1b Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 16:21:12 +01:00
Dominik Madarász e8934ac2f3 improve sprite data 2023-02-02 16:20:55 +01:00
DavoSK 755f7e7a86 Merge branch 'master' of https://github.com/zpl-c/eco2d 2023-02-02 15:43:56 +01:00
DavoSK 1f451f10be added weapon knife system 2023-02-02 15:41:16 +01:00
Dominik Madarász 91f005b4bb Add support for sprite rendering 2023-02-02 15:40:48 +01:00
Dominik Madarász 11549eb324 send notification from server 2023-02-02 14:17:53 +01:00
Dominik Madarász 65766d8748 small refactor of game layer 2023-02-02 13:24:16 +01:00
Dominik Madarász 0760d1809d sprite animation finished 2023-02-02 12:38:45 +01:00
Dominik Madarász 6e6243e9df spritesheet viewer + update flecs 2023-02-02 12:26:01 +01:00
Dominik Madarász 89fea143d3 remove dbg 2023-02-01 17:28:02 +01:00
Dominik Madarász 5aa90fc5af fix mem leak and improve spritesheet explorer 2023-02-01 17:26:52 +01:00
DavoSK bdd43143f8 implemented simple spritesheet 2023-02-01 17:10:16 +01:00
Dominik Madarász f35c9b8a1c unsigned fix 2023-02-01 15:49:13 +01:00
Dominik Madarász 6e0e747756 Merge remote-tracking branch 'origin/master' 2023-02-01 15:42:25 +01:00
DavoSK b578ceffef fix casts and make function non inlined (clang fix) 2023-02-01 15:39:51 +01:00
Dominik Madarász 3f5d999d44 survival game wip 2023-02-01 15:28:30 +01:00
Dominik Madarász 719b002989 physics impl part 2 2023-01-31 23:51:39 +01:00
Dominik Madarász 4d1a90d5cb physics impl part 1 2023-01-31 18:41:01 +01:00
Dominik Madarász 36a4a010c8 simplify prefabs 2023-01-23 15:56:02 +01:00
Dominik Madarász 1c68c73028 basic ai demo 2023-01-23 11:51:12 +01:00
Dominik Madarász 4fd2856a25 emscripten windows build scripts 2023-01-23 01:12:17 +01:00
Dominik Madarász 391106417b fix unused-but-set-variable 2023-01-23 01:02:03 +01:00
Dominik Madarász a31f4f6f25 fix web build 2023-01-23 00:58:07 +01:00
Dominik Madarász 3174b8a3c3 item router fix rolling counter 2023-01-17 10:47:16 +01:00
Dominik Madarász 267a60af32 custom UI style 2023-01-16 16:37:26 +01:00
Dominik Madarász 0e614b53a5 improve tooltip search 2023-01-16 15:46:51 +01:00
Dominik Madarász d0edc058eb tooltip search bar 2023-01-16 15:21:55 +01:00
Dominik Madarász 3165d21f2b fix padding 2023-01-16 14:45:14 +01:00
Dominik Madarász 701c15fde1 improve spacing 2023-01-16 14:23:12 +01:00
Dominik Madarász 82a8bbdaf8 wip notifications + manager 2023-01-16 14:05:15 +01:00
Dominik Madarász 847289c6de improve layouting 2023-01-16 13:23:41 +01:00
Dominik Madarász 341040abc2 embedded tooltips 2023-01-16 13:11:27 +01:00
Dominik Madarász b9e29dd7ab improve tooltips 2023-01-16 10:02:58 +01:00
Dominik Madarász c8b21e86b5 tooltip feature 2023-01-16 09:51:57 +01:00
Dominik Madarász 31cf65ad50 disable tooltip scrollbar 2023-01-15 20:42:15 +01:00
Dominik Madarász ba78e5360e add crafting tooltip 2023-01-15 20:21:56 +01:00
Dominik Madarász f24ab7dc04 prep game ui nuklear ctx 2023-01-15 19:12:28 +01:00
Dominik Madarász d51d88002d recipe filtering in crafting list 2023-01-15 18:43:03 +01:00
Dominik Madarász 553afd44d0 entity inspector addition 2023-01-15 17:44:48 +01:00
Dominik Madarász 72005402cf nuklear dev ui + asset inspector tool 2023-01-15 16:59:33 +01:00
Dominik Madarász d00ce4ec80
update flecs 2023-01-14 09:46:19 +00:00
Dominik Madarász f0ccac8e0c ecs: rework crafting to tick-based process 2023-01-14 10:24:57 +01:00
Dominik Madarász e15cdab4ff input system 2022-10-26 09:04:17 +02:00
Vladyslav Hrytsenko 4ae83ebdbb art: updated textures 2022-10-23 13:07:32 +03:00
Dominik Madarász a3a75af9b5 finish up crafting system v0 2022-10-18 19:59:35 +02:00
Vladyslav Hrytsenko 4c778d24ec art: added assembler texture 2022-10-18 20:44:10 +03:00
Dominik Madarász 5e8e760098 wip crafting ui 2022-10-18 19:37:56 +02:00
Dominik Madarász 7ecc5cd0d7 wip craft system automation improvements 2022-10-18 12:37:55 +02:00
Vladyslav Hrytsenko 80d8620ee1 art: added item plitter 2022-10-18 12:31:06 +03:00
Dominik Madarász d3e1f595e5 small recipe changes 2022-10-18 11:29:27 +02:00
Vladyslav Hrytsenko 8eec4ac470 art: updated textures 2022-10-18 11:00:19 +03:00
Dominik Madarász ee7ff6a6c3 add new items 2022-10-18 09:32:25 +02:00
Dominik Madarász f99cbc8018 Merge remote-tracking branch 'origin/master' 2022-10-18 09:22:26 +02:00
Dominik Madarász 3a008427f6 small asset ids changes 2022-10-18 09:22:11 +02:00
Vladyslav Hrytsenko 0740d0a85b art: added new textures 2022-10-18 10:13:47 +03:00
Dominik Madarász 9e368527a3 new crafting system 2022-10-18 08:57:43 +02:00
Dominik Madarász 70bb456a43 Merge remote-tracking branch 'origin/master' 2022-10-17 20:46:03 +02:00
Dominik Madarász 3d104313f8 remove typo leftover 2022-10-17 20:45:58 +02:00
Dominik Madarász e732949856
Create web-build.yml 2022-10-17 20:23:56 +02:00
Dominik Madarász 339bb56dc7 variable tick rate support 2022-10-17 20:09:30 +02:00
Dominik Madarász 4cb85f069f ItemRouter system 2022-10-17 19:44:28 +02:00
Dominik Madarász 6385ea4461 producer supports output node push 2022-10-17 18:28:40 +02:00
Dominik Madarász 3f6235e8a4 disable vsync again 2022-10-17 18:28:18 +02:00
Dominik Madarász 0d58d5f315 update 4coder stuff 2022-10-17 11:52:38 +02:00
Dominik Madarász 06f408f09f add one-shoot web win script 2022-10-17 11:06:42 +02:00
Dominik Madarász 20d35ad653 push water tex 2022-10-16 15:31:07 +02:00
Dominik Madarász 79caba208f fix producer item count again 2022-10-16 15:01:14 +02:00
Dominik Madarász 437aea7df5 tweak item list 2022-10-16 14:38:48 +02:00
Dominik Madarász 0f12724700 fix producer creating extra item 2022-10-16 14:35:10 +02:00
Dominik Madarász 3f30bb5079 fix underlying comp cache issue 2022-10-16 14:27:56 +02:00
Dominik Madarász ec6d489526 dont ask 2022-10-16 13:13:36 +02:00
Dominik Madarász bdd774fd50 enable vsync on desktop 2022-10-16 13:13:04 +02:00
Dominik Madarász 746ec9b00d enable vsync on desktop 2022-10-16 13:12:52 +02:00
Dominik Madarász 143bf1bffa dont show item proxies in item spawner 2022-10-16 13:10:21 +02:00
Dominik Madarász a824731a15 reorg texgen fallback 2022-10-16 13:02:35 +02:00
Dominik Madarász 93612f5462 improve blueprints 2022-10-16 13:00:50 +02:00
Dominik Madarász 71dc349e4e optimize world_view mapping alloc 2022-10-16 12:35:23 +02:00
Dominik Madarász 026a1e01c7 client-side block query api 2022-10-16 12:30:50 +02:00
Dominik Madarász 2527a40231 build mode ui improvements 2022-10-16 11:09:51 +02:00
Dominik Madarász b12c321488 vendor: update flecs 🎉 2022-10-16 11:09:39 +02:00
Dominik Madarász f9906ca1dd debug ui item spawner 2022-10-16 02:53:10 +02:00
Dominik Madarász fe497ae71b fix item render 2022-10-16 02:27:25 +02:00
Dominik Madarász 2d09fd90cd consider non-collision blocks as ground blocks 2022-10-16 02:13:38 +02:00
Dominik Madarász 671445d4a7 improve rendering 2022-10-16 02:00:19 +02:00
Dominik Madarász 174e5a0452 custom dim sprites 2022-10-16 01:48:23 +02:00
Dominik Madarász 50967aa046 z ordering for outer blocks + improve entity aabb collisions 2022-10-16 00:49:29 +02:00
Dominik Madarász a7622ceeec introduce a sorted render queue 2022-10-15 23:10:46 +02:00
253 changed files with 338710 additions and 23532 deletions

22
.github/workflows/web-build.yml vendored 100644
View File

@ -0,0 +1,22 @@
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_rel
build_web
build.*
build_*
emsdk
deploy_web
run_web
@ -20,3 +20,7 @@ GTAGS
pkg
pkg.zip
eco2d.zip
eco2d.db
eco2d.sublime-workspace
.cache

11
CMakePresets.json 100644
View File

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

View File

@ -1,6 +1,6 @@
<div align="center">
<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>
</div>
<h1>
eco2d
</h1>
<br />
@ -23,7 +23,7 @@
</div>
# Introduction
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.
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.
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.
* 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.
@ -90,7 +90,7 @@ build\eco2d.exe -?
```
# License
zpl.eco2d code is licensed under the BSD 3-Clause license, as seen [here](LICENSE).
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.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 824 B

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

BIN
art/gen/enemy1.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

BIN
art/gen/log.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

BIN
art/gen/plank.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

BIN
art/gen/player.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
art/gen/screws.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

BIN
art/gen/water0.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

BIN
art/gen/water1.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

BIN
art/gen/water2.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

After

Width:  |  Height:  |  Size: 278 B

View File

@ -0,0 +1,28 @@
-- 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

@ -0,0 +1,46 @@
-- 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

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

View File

@ -0,0 +1,18 @@
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

@ -0,0 +1,42 @@
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

@ -0,0 +1,72 @@
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.

BIN
art/skins/gwen.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

3
build_dbg.bat 100644
View File

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

View File

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

View File

@ -0,0 +1,58 @@
#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,6 +3,7 @@
#include "platform/platform.h"
#include "world/world.h"
#include "pkt/packet.h"
#include "models/database.h"
#include "platform/signal_handling.h"
#include "net/network.h"
#include "models/entity.h"
@ -10,6 +11,7 @@
#include "world/entity_view.h"
#include "core/camera.h"
#include "platform/profiler.h"
#include "platform/renderer.h"
#include "flecs/flecs_os_api_stdcpp.h"
#include "flecs.h"
@ -21,12 +23,19 @@
#include "packets/pkt_01_welcome.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_should_close;
static world_view *world_viewers;
static world_view *active_viewer;
struct nk_context *game_ui = 0;
static WORLD_PKT_READER(pkt_reader) {
pkt_header header = {0};
uint32_t ok = pkt_header_decode(&header, data, datalen);
@ -92,7 +101,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)));
}
void game_world_view_set_active_by_idx(uint16_t idx) {
ZPL_ASSERT(idx >= 0 && idx < zpl_buffer_count(world_viewers));
ZPL_ASSERT(idx < zpl_buffer_count(world_viewers));
game_world_view_set_active(&world_viewers[idx]);
}
@ -125,9 +134,12 @@ float game_time() {
return (float)get_cached_time();
}
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_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) {
game_mode = play_mode;
game_should_close = false;
entity_default_spawnlist();
game_init(db_init());
#ifndef _DEBUG
const char *host_ip = "lab.zakto.pw";
@ -147,6 +159,9 @@ void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_
world_viewers_init(num_viewers);
active_viewer = &world_viewers[0];
camera_reset();
Font font = LoadFontEx("art/anonymous_pro_bold.ttf", 14, 0, 0);
game_ui = InitNuklearEx(font, 14);
}
if (game_mode != GAMEKIND_SINGLE) {
@ -167,6 +182,8 @@ void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_
//ecs_set_target_fps(world_ecs(), 60);
}
}
game_init_ecs();
if (game_mode == GAMEKIND_SINGLE) {
for (uint32_t i = 0; i < num_viewers; i++) {
@ -180,6 +197,7 @@ int8_t game_is_networked() {
}
void game_shutdown() {
db_shutdown();
if (game_mode == GAMEKIND_CLIENT) {
network_client_disconnect();
@ -200,7 +218,8 @@ void game_shutdown() {
// TODO(zaklaus): crashes on exit
//platform_shutdown();
}
UnloadNuklear(game_ui);
}
}
uint8_t game_is_running() {
@ -215,13 +234,14 @@ game_kind game_get_kind(void) {
return game_mode;
}
void game_input() {
void game_core_input() {
if (game_mode != GAMEKIND_HEADLESS) {
platform_input();
UpdateNuklear(game_ui);
}
}
void game_update() {
void game_core_update() {
static double last_update = 0.0f;
if (game_mode == GAMEKIND_CLIENT) {
network_client_tick();
@ -243,12 +263,16 @@ void game_update() {
last_update = get_cached_time();
}
void game_render() {
void game_core_render() {
if (game_mode != GAMEKIND_HEADLESS) {
platform_render();
}
}
void game_draw_ui() {
DrawNuklear(game_ui);
}
void game_action_send_keystate(game_keystate_data *data) {
pkt_send_keystate_send(active_viewer->view_id, data);
}
@ -267,3 +291,71 @@ void game_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,6 +2,7 @@
#include "platform/system.h"
#include "world/world_view.h"
#include "packets/pkt_send_keystate.h"
#include "packets/pkt_send_code.h"
typedef enum {
GAMEKIND_SINGLE,
@ -10,7 +11,7 @@ typedef enum {
FORCE_GAMEKIND_UINT8 = UINT8_MAX
} game_kind;
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_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_shutdown();
void game_request_close();
uint8_t game_is_running();
@ -19,9 +20,24 @@ float game_time();
game_kind game_get_kind(void);
//~ 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_update();
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
world_view *game_world_view_get_active(void);
@ -32,6 +48,7 @@ void game_world_view_set_active(world_view *view);
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));
entity_view *game_world_view_active_get_entity(uint64_t ent_id);
void game_world_view_render_world(void);
//~ NOTE(zaklaus): viewer -> host actions
void game_action_send_keystate(game_keystate_data *data);

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
#include "debug/debug_ui.h"
#include "debug/debug_draw.h"
#include "dev/debug_ui.h"
#include "dev/debug_draw.h"
#include "raylib.h"
#include "models/prefabs/vehicle.h"
#include "core/camera.h"
@ -9,6 +9,10 @@
#include "models/components.h"
ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0)
#include "raylib-nuklear.h"
ZPL_DIAGNOSTIC_POP
typedef enum {
DITEM_RAW,
DITEM_GAP,
@ -16,7 +20,9 @@ typedef enum {
DITEM_BUTTON,
DITEM_SLIDER,
DITEM_LIST,
DITEM_TOOL,
DITEM_COND,
DITEM_END,
DITEM_FORCE_UINT8 = UINT8_MAX
@ -41,6 +47,8 @@ static uint8_t is_debug_open = 1;
static uint8_t is_handle_ctrl_held;
static float debug_xpos = DBG_START_XPOS;
static float debug_ypos = DBG_START_YPOS;
static zpl_u16 sel_item_id = 0;
static struct nk_context *dev_ui = 0;
typedef enum {
L_NONE = 0,
@ -71,6 +79,11 @@ typedef struct debug_item {
void (*on_change)(float);
} slider;
struct {
uint8_t is_open;
void (*on_draw)(void);
} tool;
void (*on_click)(void);
uint8_t (*on_success)(void);
@ -82,10 +95,13 @@ typedef struct debug_item {
static void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color);
static int UIMeasureText(const char *text, int fontSize);
#include "debug/debug_replay.c"
#include "dev/debug_replay.c"
#include "debug/debug_ui_actions.c"
#include "debug/debug_ui_widgets.c"
#include "gui/ui_skin.c"
#include "dev/debug_ui_actions.c"
#include "dev/debug_ui_widgets.c"
#include "dev/debug_ui_tools.c"
static debug_item items[] = {
{
@ -133,17 +149,24 @@ static debug_item items[] = {
.list = {
.is_collapsed = true,
.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 = "erase world changes", .on_click = ActEraseWorldChanges },
{ .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,
.name = "demo npcs",
@ -232,12 +255,27 @@ static debug_item items[] = {
{ .kind = DITEM_RAW, .val = PROF_RENDER, .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_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 },
},
.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)
{
.kind = DITEM_BUTTON,
@ -340,6 +378,25 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
ypos += DBG_FONT_SPACING;
}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: {
}break;
@ -353,6 +410,19 @@ void debug_draw(void) {
// NOTE(zaklaus): Flush old debug samples
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 ypos = debug_ypos;
@ -397,6 +467,8 @@ 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, ypos, 0);
}
DrawNuklear(dev_ui);
}
debug_area_status check_mouse_area(float xpos, float ypos, float w, float h) {

View File

@ -1,8 +1,10 @@
#include "debug/debug_ui.h"
#include "dev/debug_ui.h"
#include "world/blocks.h"
#include "models/items.h"
#include "net/network.h"
#include "models/entity.h"
void
ActExitGame(void) {
game_request_close();
@ -22,89 +24,34 @@ ActSpawnCar(void) {
}
void
ActSpawnCoal(void) {
ecs_entity_t e = item_spawn(ASSET_COAL, 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_ICEMAKER_ITEM);
ActSpawnItemPrev(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
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);
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
ActSpawnBelt(void) {
ecs_entity_t e = item_spawn(ASSET_BELT, 32);
ActSpawnSelItem(void) {
ecs_entity_t e = item_spawn(sel_item_id, 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);
entity_set_position(e, origin->x, origin->y);
}
void
@ -285,8 +232,7 @@ ActSpawnDemoNPCs(void) {
if (zpl_array_count(demo_npcs) >= 100000) return;
for (uint32_t i = 0; i < 1000; i++) {
uint64_t e = entity_spawn(EKIND_DEMO_NPC);
ecs_add(world_ecs(), e, DemoNPC);
uint64_t e = entity_spawn_id(ASSET_CREATURE);
Position *pos = ecs_get_mut(world_ecs(), e, Position);
pos->x=(float)(rand() % world_dim());
pos->y=(float)(rand() % world_dim());

View File

@ -0,0 +1,143 @@
// 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

@ -1,4 +1,4 @@
#include "debug/debug_ui.h"
#include "dev/debug_ui.h"
#include "raylib.h"
#include "platform/platform.h"
#include "net/network.h"
@ -119,6 +119,11 @@ DrawDemoNPCCount(debug_item *it, float xpos, float ypos) {
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
static inline debug_draw_result

View File

@ -7,11 +7,9 @@ Texture2D texgen_build_anim_fallback(asset_id id, int64_t counter) {
(void)counter;
switch (id) {
case ASSET_WATER: {
Image img = LoadImageEco("water");
ImageColorBrightness(&img, zpl_abs((counter % 64 - 32)*2));
return Image2TexEco(img);
return LoadTexEco(zpl_bprintf("%s%d", "water", counter%3));
}break;
default: return GenColorEco(PINK); break;
}
}
@ -21,12 +19,18 @@ Texture2D texgen_build_sprite_fallback(asset_id id) {
case ASSET_BLANK: return GenColorEco(WHITE); break;
case ASSET_BUILDMODE_HIGHLIGHT: return GenColorEco(WHITE); break;
case ASSET_BLOCK_FRAME: return GenFrameRect(); break;
case ASSET_BIG_TREE: return LoadTexEco("bigtree"); break;
// NOTE(zaklaus): items
case ASSET_COAL: return LoadTexEco("coal");
case ASSET_BLUEPRINT: return LoadTexEco("blueprint");
case ASSET_IRON_ORE: return LoadTexEco("iron_ore");
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
case ASSET_FENCE: return LoadTexEco("fence");
case ASSET_GROUND: return LoadTexEco("grass");
@ -36,19 +40,29 @@ Texture2D texgen_build_sprite_fallback(asset_id id) {
case ASSET_HILL: return LoadTexEco("rock");
case ASSET_LAVA: return LoadTexEco("lava");
case ASSET_WOOD: return LoadTexEco("wood");
case ASSET_TREE: return LoadTexEco("tree");
case ASSET_TREE: return LoadTexEco("bigtree");
case ASSET_TEST_TALL: return LoadTexEco("test-tall");
// case ASSET_WATER: return LoadTexEco("water");
case ASSET_BELT:
case ASSET_BELT_RIGHT: return LoadTexEco("belt_right");
case ASSET_BELT_LEFT: return LoadTexEco("belt_left");
case ASSET_BELT_UP: return LoadTexEco("belt_up");
case ASSET_BELT_DOWN: return LoadTexEco("belt_down");
// NOTE(zaklaus): devices
case ASSET_CHEST: return LoadTexEco("chest");
case ASSET_FURNACE: return LoadTexEco("furnace-export");
default: return GenColorEco(PINK); break;
case ASSET_FURNACE: return LoadTexEco("furnace");
case ASSET_CRAFTBENCH: return LoadTexEco("craftbench");
case ASSET_SPLITTER: return LoadTexEco("item_splitter");
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);
cam.x = (double)mx;
cam.y = (double)my;
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BLOCK_FRAME, WHITE);
// NOTE(zaklaus): Check distance
double dx = old_cam.x - cam.x;
double dy = old_cam.y - cam.y;
double dsq = (dx*dx + dy*dy);
bool is_outside_range = (dsq > zpl_square(WORLD_BLOCK_SIZE*14));
if (build_submit_placements) {
build_submit_placements = false;
buildmode_clear_buffers();
}
if (IsKeyPressed(KEY_B)){
if (input_is_pressed(IN_TOGGLE_DEMOLITION)){
build_is_deletion_mode = !build_is_deletion_mode;
}
Item *item = &e->items[e->selected_item];
if (e->has_items && !e->inside_vehicle && item->quantity > 0 && (!is_outside_range || build_is_deletion_mode)) {
if (e->has_items && !e->inside_vehicle && (build_is_deletion_mode || (item->quantity > 0 && !is_outside_range))) {
item_usage usage = 0;
uint16_t item_id = 0;
if (!build_is_deletion_mode){
@ -60,20 +60,21 @@ void buildmode_draw(void) {
build_num_placements = 0;
buildmode_clear_buffers();
}
uint32_t qty = BUILD_MAX_PLACEMENTS;
bool directional = false;
if (!build_is_deletion_mode){
directional = item_get_place_directional(item_id);
qty = item->quantity;
}
world_block_lookup l = world_block_from_realpos((float)cam.x, (float)cam.y);
world_view_block_lookup l = world_view_block_from_realpos(game_world_view_get_active(), (float)cam.x, (float)cam.y);
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;
}
if (build_is_in_draw_mode) {
for (size_t i = 0; i < BUILD_MAX_PLACEMENTS; i++) {
item_placement *it = &build_placements[i];
@ -89,7 +90,7 @@ void buildmode_draw(void) {
float sy = zpl_sign0(p2y-p1y);
float sxx = zpl_sign0(p3x-p1x);
float syy = zpl_sign0(p3y-p1y);
if (sx != sxx || sy != syy) break;
}
it->x = (float)cam.x;
@ -102,31 +103,35 @@ void buildmode_draw(void) {
}
}
}
if (!is_outside_range)
renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : WHITE, 0.2f));
if (!is_outside_range) {
if (build_is_deletion_mode)
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_num_placements = zpl_min(build_num_placements, qty);
}
}
for (size_t i = 0; i < build_num_placements; i++) {
item_placement *it = &build_placements[i];
renderer_draw_single(it->x, it->y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : WHITE, 0.4f));
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));
}
if (build_is_in_draw_mode) {
if (IsKeyPressed(KEY_SPACE)) {
build_is_in_draw_mode = false;
buildmode_clear_buffers();
}
if (IsMouseButtonReleased(MOUSE_RIGHT_BUTTON)) {
build_submit_placements = true;
build_is_in_draw_mode = false;
}
}
}

View File

@ -1,16 +1,19 @@
#include "models/crafting.h"
typedef struct {
uint8_t selected_item;
bool drop_item;
bool item_is_held;
uint8_t held_item_idx;
Item held_item;
bool is_inside;
bool storage_action;
bool swap;
uint8_t swap_from;
uint8_t swap_to;
uint16_t craft_item;
} inv_keystate;
static inv_keystate player_inv = {0};
@ -21,31 +24,147 @@ bool inv_is_inside = false;
bool inv_is_storage_action = 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){
if (!e->has_items && is_player)
return;
if (!e->has_storage_items && !is_player)
return;
float x = sx;
float y = sy;
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_cols = (is_player) ? 3 : 4;
inv_keystate *inv = (!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 |= inv->is_inside;
inv_is_inside |= inv->is_inside || inside_craft;
for (int32_t i = 0; i < inv_size; i += 1) {
{
debug_area_status area = check_mouse_area(x, y, 64, 64);
Color color = RAYWHITE;
Item *item = (is_player) ? &e->items[i] : &e->storage_items[i];
if (area == DAREA_HOVER) {
color = YELLOW;
} else if (area == DAREA_PRESS && inv2->item_is_held){
@ -79,30 +198,34 @@ void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
} else if (i == inv->selected_item) {
color = RED;
}
DrawRectangleLinesEco(x, y, 64, 64, color);
if (item->quantity > 0) {
DrawTexturePro(GetSpriteTexture2D(assets_find(item->kind)), ASSET_SRC_RECT(), ASSET_DST_RECT(x,y), (Vector2){0.5f,0.5f}, 0.0f, WHITE);
Texture2D tex = GetSpriteTexture2D(assets_find(item->kind));
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) {
DrawTextEco(zpl_bprintf("%d", item->quantity), x+5, y+5, 16, RAYWHITE, 0.0f);
}
if (item->quantity > 0 && item->durability < 1.0f) {
DrawRectangleEco(x, y+56, 64, 8, BLACK);
DrawRectangleEco(x, y+56, 64*item->durability, 8, BlendColor(RED, GREEN, item->durability));
}
}
x += 64;
if ((i+1) % inv_cols == 0) {
x = sx;
y += 64;
}
}
// NOTE(zaklaus): switch it off if is_player
if (is_player)
inv_is_storage_action = false;
@ -111,14 +234,18 @@ void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
void inventory_render_held_item(bool is_player){
inv_keystate *inv = (!is_player) ? &storage_inv : &player_inv;
inv_keystate *inv2 = (is_player) ? &storage_inv : &player_inv;
if (inv->item_is_held) {
Vector2 mpos = GetMousePosition();
mpos.x -= 32;
mpos.y -= 32;
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));
Texture2D tex = GetSpriteTexture2D(assets_find(inv->held_item.kind));
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);
if (!inv->is_inside && IsMouseButtonReleased(MOUSE_LEFT_BUTTON) && !inv2->is_inside) {
inv->drop_item = true;
inv->item_is_held = false;
@ -130,6 +257,7 @@ void inventory_render_held_item(bool is_player){
void inventory_reset_states(inv_keystate *ik) {
ik->drop_item = false;
ik->swap = false;
ik->craft_item = 0;
}
void inventory_draw() {
@ -138,22 +266,22 @@ void inventory_draw() {
inv_swap_storage = false;
inventory_reset_states(&player_inv);
inventory_reset_states(&storage_inv);
camera cam = camera_get();
entity_view *e = game_world_view_active_get_entity(cam.ent_id);
if (!e || !e->has_items) return;
if (IsKeyPressed(KEY_TAB)) {
if (input_is_pressed(IN_TOGGLE_INV)) {
inv_is_open = !inv_is_open;
}
if (!inv_is_open || build_is_in_draw_mode) {
return;
}
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_render_held_item(true);
inventory_render_held_item(false);
}

View File

@ -0,0 +1,112 @@
#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

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

View File

@ -0,0 +1,14 @@
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

@ -0,0 +1,254 @@
// 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

@ -0,0 +1,483 @@
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

@ -1,46 +0,0 @@
#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

@ -1,44 +0,0 @@
#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

@ -1,29 +0,0 @@
#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

@ -1,16 +0,0 @@
// 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

@ -1,27 +0,0 @@
#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

@ -1,105 +0,0 @@
#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,47 +1,79 @@
#include "models/assets.h"
#include "raylib.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 {
asset_id id;
asset_kind kind;
union {
Texture2D tex;
Sound snd;
};
// NOTE(zaklaus): metadata
} asset;
#include "lists/assets_list.c"
//#include "lists/assets_list.c"
static asset *assets;
#define ASSET_FRAME_RENDER_MS (1.0/5.0)
#define ASSETS_COUNT (zpl_array_count(assets))
#define ASSET_FRAME_RENDER_MS (1.0/1.0)
#define ASSET_FRAME_SKIP 4
static int64_t assets_frame_counter = 1;
static double assets_frame_next_draw = 0.0;
#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) {
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
asset *b = &assets[i];
switch (b->kind) {
case AKIND_TEXTURE: {
b->tex = texgen_build_sprite(b->id);
}break;
case AKIND_ANIM: {
b->tex = texgen_build_anim(b->id, 0);
}break;
case AKIND_SOUND: {
// TODO(zaklaus): soundgen
}break;
default: break;
}
}
@ -53,21 +85,21 @@ int32_t assets_frame(void) {
if (assets_frame_next_draw < get_cached_time()) {
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
asset *b = &assets[i];
switch (b->kind) {
case AKIND_ANIM: {
UnloadTexture(b->tex);
b->tex = texgen_build_anim(b->id, assets_frame_counter);
}break;
default: break;
}
}
assets_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
assets_frame_counter += ASSET_FRAME_SKIP;
}
return 0;
}
@ -78,11 +110,11 @@ void assets_destroy(void) {
case AKIND_TEXTURE: {
UnloadTexture(assets[i].tex);
}break;
case AKIND_SOUND: {
// TODO(zaklaus): soundgen
}break;
default: break;
}
}
@ -93,8 +125,8 @@ uint16_t assets_find(asset_id id) {
if (assets[i].id == id)
return i;
}
ZPL_PANIC("Unknown asset id: %d\n", id);
//ZPL_PANIC("Unknown asset id: %d\n", id);
return ASSET_INVALID;
}
@ -102,6 +134,11 @@ asset_kind assets_get_kind(uint16_t id) {
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) {
return (void*)&assets[id].snd;;
}
@ -109,3 +146,9 @@ void *assets_get_snd(uint16_t id) {
void *assets_get_tex(uint16_t id) {
return (void*)&assets[id].tex;
}
const char *asset_names[] = {
#define X(id) #id,
_ASSETS
#undef X
};

View File

@ -1,7 +1,7 @@
#pragma once
#include "platform/system.h"
#include "lists/assets_ids.h"
#include "assets_ids.h"
typedef enum {
AKIND_TEXTURE,
@ -11,6 +11,9 @@ typedef enum {
FORCE_AKIND_UINT8 = UINT8_MAX
} 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_frame(void);
void assets_destroy(void);
@ -18,9 +21,13 @@ void assets_destroy(void);
uint16_t assets_find(asset_id 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_tex(uint16_t id);
uint16_t assets_resolve_proxy(uint16_t id);
// NOTE(zaklaus): client only
#define ASSET_SRC_RECT() ((Rectangle){0, 0, 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,51 +1,15 @@
#include "models/components.h"
ECS_COMPONENT_DECLARE(Vector2D);
ECS_COMPONENT_DECLARE(Position);
ECS_COMPONENT_DECLARE(Velocity);
ECS_COMPONENT_DECLARE(Chunk);
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);
#define X(comp) ECS_COMPONENT_DECLARE(comp);
_COMPS
#undef X
void ComponentsImport(ecs_world_t *ecs) {
ECS_MODULE(ecs, Components);
ECS_COMPONENT_DEFINE(ecs, Vector2D);
ECS_COMPONENT_DEFINE(ecs, Position);
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);
#define X(comp) ECS_COMPONENT_DEFINE(ecs, comp);
_COMPS
#undef X
}

View File

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

View File

@ -0,0 +1,216 @@
#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

@ -0,0 +1,50 @@
#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

@ -0,0 +1,191 @@
#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

@ -0,0 +1,28 @@
#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,8 +8,44 @@
#include "systems/systems.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
#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) {
ecs_entity_t e = ecs_new(world_ecs(), 0);
@ -18,20 +54,13 @@ uint64_t entity_spawn(uint16_t class_id) {
entity_wake(e);
if (class_id != EKIND_SERVER) {
ecs_set(world_ecs(), e, Velocity, {0});
Position *pos = ecs_get_mut(world_ecs(), e, Position);
#if 1
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_track(world_collision_grid(), e);
ecs_set(world_ecs(), e, Velocity, { 0 });
entity_set_position(e, (float)(rand() % world_dim()), (float)(rand() % world_dim()));
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;
@ -56,8 +85,19 @@ uint64_t entity_spawn_id_with_data(uint16_t id, void *udata){
}
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) {
for (size_t i = 0; i < num_ids; i++ ) {
librg_entity_untrack(world_collision_grid(), ids[i]);
librg_entity_untrack(world_tracker(), ids[i]);
ecs_delete(world_ecs(), ids[i]);
}
@ -65,14 +105,17 @@ void entity_batch_despawn(uint64_t *ids, size_t num_ids) {
void entity_despawn(uint64_t ent_id) {
librg_entity_untrack(world_tracker(), ent_id);
librg_entity_untrack(world_collision_grid(), ent_id);
ecs_delete(world_ecs(), ent_id);
}
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);
p->x = x;
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_collision_grid(), ent_id, librg_chunk_from_realpos(world_collision_grid(), x, y, 0));
entity_wake(ent_id);
}

View File

@ -6,10 +6,16 @@
uint64_t entity_spawn(uint16_t class_id /* 0 = no streaming */);
uint64_t entity_spawn_id(uint16_t id);
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_despawn(uint64_t ent_id);
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
void entity_wake(uint64_t ent_id);

View File

@ -3,16 +3,72 @@
#include "world/entity_view.h"
#include "world/world.h"
#include "world/blocks.h"
#include "models/database.h"
#include "models/components.h"
#include "zpl.h"
#include "lists/items_list.c"
#define ITEMS_COUNT (sizeof(items)/sizeof(item_desc))
//#include "lists/items_list.c"
static item_desc *items;
#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) {
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
ZPL_ASSERT(id < ITEMS_COUNT);
item_usage usage = items[id].usage;
if (usage == UKIND_PROXY) {
return item_find(items[id].proxy.id);
@ -32,7 +88,7 @@ void item_show(uint64_t ent, bool show) {
uint64_t item_spawn(asset_id kind, uint32_t qty) {
ecs_entity_t e = entity_spawn(EKIND_ITEM);
Item *d = ecs_get_mut(world_ecs(), e, Item);
*d = (Item){
.kind = item_fix_kind(kind),
@ -40,32 +96,26 @@ uint64_t item_spawn(asset_id kind, uint32_t qty) {
.merger_time = 0,
.durability = 1.0f,
};
item_desc *it = &items[item_find(kind)];
if (it->has_storage) {
ecs_add(world_ecs(), e, BlockHarvest);
ItemContainer *storage = ecs_get_mut(world_ecs(), e, ItemContainer);
*storage = (ItemContainer){0};
}
switch (it->attachment) {
case UDATA_ENERGY_SOURCE: {
EnergySource *f = ecs_get_mut(world_ecs(), e, EnergySource);
*f = (EnergySource){
.kind = it->energy_source.producer,
.energy_level = it->energy_source.energy_level,
};
} 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;
case UDATA_ENERGY_SOURCE: {
EnergySource *f = ecs_get_mut(world_ecs(), e, EnergySource);
*f = (EnergySource){
.kind = it->energy_source.producer,
.energy_level = it->energy_source.energy_level,
};
} break;
default: break;
}
return (uint64_t)e;
}
@ -77,11 +127,17 @@ item_id item_find(asset_id kind) {
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) {
if (!world_entity_valid(ent)) return NULL;
// 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);
return ecs_get_mut_if(world_ecs(), ent, Item);
}
const Item *item_get_data_const(uint64_t ent) {
@ -102,7 +158,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);
item_id item_asset_id = item_find(item_asset);
if (item_asset_id == ASSET_INVALID) return;
// NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it
if (item_asset_id == it_id) {
it->quantity++;
@ -117,7 +173,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));
it->quantity--;
}break;
case UKIND_PLACE_ITEM:{
world_block_lookup l = world_block_from_realpos(p.x, p.y);
if (l.is_outer && l.bid > 0) {
@ -127,14 +183,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)) {
return;
}
ecs_entity_t e = entity_spawn_id(desc->place_item.id);
ZPL_ASSERT(world_entity_valid(e));
entity_set_position(e, p.x, p.y);
it->quantity--;
}break;
case UKIND_PLACE_ITEM_DATA:{
world_block_lookup l = world_block_from_realpos(p.x, p.y);
if (l.is_outer && l.bid > 0) {
@ -144,14 +200,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)) {
return;
}
ecs_entity_t e = entity_spawn_id_with_data(desc->place_item.id, desc);
ZPL_ASSERT(world_entity_valid(e));
entity_set_position(e, p.x, p.y);
it->quantity--;
}break;
case UKIND_DELETE:
case UKIND_END_PLACE:
case UKIND_PROXY:
@ -164,16 +220,21 @@ void item_despawn(uint64_t id) {
}
uint32_t item_max_quantity(item_id id) {
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
ZPL_ASSERT(id < ITEMS_COUNT);
return items[id].max_quantity;
}
item_usage item_get_usage(item_id id) {
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
ZPL_ASSERT(id < ITEMS_COUNT);
return items[id].usage;
}
bool item_get_place_directional(item_id id) {
ZPL_ASSERT(id >= 0 && id < ITEMS_COUNT);
ZPL_ASSERT(id < ITEMS_COUNT);
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_DATA,
UKIND_END_PLACE,
// NOTE(zaklaus): the rest of possible actions
UKIND_HOLD,
UKIND_PROXY,
@ -21,7 +21,6 @@ typedef enum {
typedef enum {
UDATA_NONE,
UDATA_ENERGY_SOURCE,
UDATA_INGREDIENT,
} item_attachment;
typedef struct {
@ -30,36 +29,30 @@ typedef struct {
item_attachment attachment;
uint32_t max_quantity;
uint8_t has_storage;
// NOTE(zaklaus): usage data
union {
struct {
asset_id kind;
bool directional; // NOTE(zaklaus): expects next 4 asset entries to be direction assets
} place;
struct {
asset_id id;
} proxy;
struct {
asset_id id;
} place_item;
};
union {
struct {
asset_id producer;
float energy_level;
} energy_source;
struct {
asset_id producer;
asset_id product;
asset_id additional_ingredient;
} ingredient;
};
// NOTE: item data
union {
struct {
@ -72,6 +65,8 @@ typedef struct {
typedef uint16_t item_id;
void item_db(void);
// NOTE(zaklaus): item drops
void item_show(uint64_t ent, bool show);
@ -80,6 +75,7 @@ void item_despawn(uint64_t id);
// NOTE(zaklaus): items
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);
Item *item_get_data(uint64_t ent);
const Item *item_get_data_const(uint64_t ent);
@ -87,3 +83,4 @@ const Item *item_get_data_const(uint64_t ent);
uint32_t item_max_quantity(item_id id);
item_usage item_get_usage(item_id id);
bool item_get_place_directional(item_id id);
item_desc item_get_desc(item_id id);

View File

@ -1,30 +0,0 @@
#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

@ -1,8 +0,0 @@
#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

@ -1,22 +0,0 @@
#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

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

View File

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

View File

@ -0,0 +1,120 @@
#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

@ -1,18 +0,0 @@
#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

@ -1,7 +0,0 @@
#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