Compare commits
No commits in common. "master" and "isolation_bkp/dynres" have entirely different histories.
master
...
isolation_
|
@ -1,22 +0,0 @@
|
|||
name: Build web and deploy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Release
|
||||
BUTLER_API_KEY: ${{ secrets.BUTLER_KEY }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up emsdk
|
||||
run: web/setup.sh
|
||||
|
||||
- name: Build and deploy eco2d
|
||||
run: web/deploy.sh
|
|
@ -1,6 +1,6 @@
|
|||
build
|
||||
build.*
|
||||
build_*
|
||||
build_rel
|
||||
build_web
|
||||
emsdk
|
||||
deploy_web
|
||||
run_web
|
||||
|
@ -20,7 +20,3 @@ GTAGS
|
|||
pkg
|
||||
pkg.zip
|
||||
eco2d.zip
|
||||
eco2d.db
|
||||
eco2d.sublime-workspace
|
||||
|
||||
.cache
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"version": 2,
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "vs2022-debug",
|
||||
"displayName": "Visual Studio Community 2022 Release - x86_amd64 - Debug",
|
||||
"configurePreset": "vs2022",
|
||||
"configuration": "Debug"
|
||||
}
|
||||
]
|
||||
}
|
12
README.md
|
@ -1,6 +1,6 @@
|
|||
<h1>
|
||||
eco2d
|
||||
</h1>
|
||||
<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>
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
</div>
|
||||
|
||||
# Introduction
|
||||
eco2d is a experimental set of games made out of curiosity. It attempts to bridge several libraries to create a playable sandbox with ease of extensibility and with performance in mind. The goal is not to make a generic 2D game engine but to build a game prototype that anyone can use to build various experiments.
|
||||
zpl.eco2d is a small framework/game engine made out of curiosity. It attempts to bridge several libraries to create a playable sandbox with ease of extensibility and with performance in mind. The goal is not to make a generic 2D game engine but to build a game prototype that anyone can use to build various experiments.
|
||||
|
||||
The game runs on top of [raylib](https://raylib.com/) technologies and makes use of the [zpl](https://zpl.pw/) ecosystem alongside the **cwpack** library for data serialization. The game logic and lifecycle are maintained using [flecs](https://github.com/SanderMertens/flecs/) library and its suite of tools that help us improve the development efficiency.
|
||||
|
||||
|
@ -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
|
||||
eco2d code is licensed under the BSD 3-Clause license, as seen [here](LICENSE).
|
||||
zpl.eco2d code is licensed under the BSD 3-Clause license, as seen [here](LICENSE).
|
||||
|
||||
Assets under the **art** folder are released into [Public Domain](https://creativecommons.org/share-your-work/public-domain/cc0/) unless otherwise stated.
|
||||
|
||||
|
|
Before Width: | Height: | Size: 474 B |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 430 B After Width: | Height: | Size: 2.9 KiB |
BIN
art/gen/coal.png
Before Width: | Height: | Size: 452 B |
Before Width: | Height: | Size: 559 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 901 B |
Before Width: | Height: | Size: 422 B |
Before Width: | Height: | Size: 553 B |
Before Width: | Height: | Size: 366 B |
Before Width: | Height: | Size: 528 B |
BIN
art/gen/log.png
Before Width: | Height: | Size: 423 B |
Before Width: | Height: | Size: 382 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 588 B |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 592 B |
Before Width: | Height: | Size: 581 B |
Before Width: | Height: | Size: 624 B |
Before Width: | Height: | Size: 156 B |
BIN
art/gen/wood.png
Before Width: | Height: | Size: 278 B After Width: | Height: | Size: 254 B |
|
@ -1,28 +0,0 @@
|
|||
-- typedef enum {
|
||||
-- BLOCK_FLAG_COLLISION = (1 << 1),
|
||||
-- BLOCK_FLAG_HAZARD = (1 << 2),
|
||||
-- BLOCK_FLAG_ESSENTIAL = (1 << 3),
|
||||
-- BLOCK_FLAG_DESTROY_ON_COLLISION = (1 << 4),
|
||||
-- BLOCK_FLAG_ENTITY = (1 << 5),
|
||||
-- } block_flags;
|
||||
|
||||
INSERT INTO blocks (kind, flags, drag, friction, bounce, velx, vely) VALUES
|
||||
(asset('EMPTY'), NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('GROUND'), NULL, 1.0, 1.0, NULL, NULL, NULL),
|
||||
(asset('DIRT'), NULL, 2.1, 1.0, NULL, NULL, NULL),
|
||||
(asset('WALL'), (1<<1), 1.0, 1.0, 1.0, NULL, NULL),
|
||||
(asset('HILL'), (1<<1), 1.0, 1.0, NULL, NULL, NULL),
|
||||
(asset('HILL_SNOW'), (1<<1), 1.0, 1.0, NULL, NULL, NULL),
|
||||
(asset('WATER'), 0, 0.11, 1.0, NULL, NULL, NULL),
|
||||
(asset('LAVA'), (1<<2), 6.2, 4.0, NULL, NULL, NULL),
|
||||
(asset('FENCE'), (1<<1), 1.0, 1.0, 1.0, NULL, NULL),
|
||||
(asset('WOOD'), (1<<1), 1.0, 1.0, 0.0, NULL, NULL),
|
||||
(asset('TREE'), (1<<1)|(1<<4), 1.0, 1.0, 0.0, NULL, NULL),
|
||||
(asset('CHEST'), (1<<5), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('FURNACE'), (1<<5), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('TEST_TALL'), (1<<1), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('BELT_LEFT'), NULL, 1.0, 1.0, NULL, -150.0, NULL),
|
||||
(asset('BELT_RIGHT'), NULL, 1.0, 1.0, NULL, 150.0, NULL),
|
||||
(asset('BELT_UP'), NULL, 1.0, 1.0, NULL, NULL, -150.0),
|
||||
(asset('BELT_DOWN'), NULL, 1.0, 1.0, NULL, NULL, 150.0);
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
-- typedef enum {
|
||||
-- // NOTE(zaklaus): hardcoded fields for placement ops
|
||||
-- UKIND_DELETE,
|
||||
-- UKIND_PLACE,
|
||||
-- UKIND_PLACE_ITEM,
|
||||
-- UKIND_PLACE_ITEM_DATA,
|
||||
-- UKIND_END_PLACE,
|
||||
--
|
||||
-- // NOTE(zaklaus): the rest of possible actions
|
||||
-- UKIND_HOLD,
|
||||
-- UKIND_PROXY,
|
||||
-- } item_usage;
|
||||
--
|
||||
-- typedef enum {
|
||||
-- UDATA_NONE,
|
||||
-- UDATA_ENERGY_SOURCE,
|
||||
-- } item_attachment;
|
||||
|
||||
INSERT INTO items (kind, usage, attachment, max_quantity, place_kind, directional,
|
||||
proxy_id, place_item_id, producer, energy_level, blueprint_w, blueprint_h, blueprint_plan)
|
||||
VALUES
|
||||
(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('FENCE'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('COAL'), 5, 1, 64, NULL, NULL, NULL, NULL, asset('FURNACE'), 15.0, NULL, NULL, NULL),
|
||||
(asset('WOOD'), 1, 0, 64, asset('WOOD'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('TREE'), 1, 0, 64, asset('TREE'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('TEST_TALL'), 1, 0, 64, asset('TEST_TALL'), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('BELT'), 1, 0, 999, asset('BELT'), 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('BELT_LEFT'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('BELT_RIGHT'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('BELT_UP'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('BELT_DOWN'), 6, 0, NULL, NULL, NULL, asset('BELT'), NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('CHEST'), 2, 0, 32, NULL, NULL, NULL, asset('CHEST'), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('CRAFTBENCH'), 2, 0, 32, NULL, NULL, NULL, asset('CRAFTBENCH'), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('FURNACE'), 2, 0, 32, NULL, NULL, NULL, asset('FURNACE'), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('SPLITTER'), 2, 0, 32, NULL, NULL, NULL, asset('SPLITTER'), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('ASSEMBLER'), 2, 0, 32, NULL, NULL, NULL, asset('ASSEMBLER'), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('CREATURE'), 2, 0, 32, NULL, NULL, NULL, asset('CREATURE'), NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('IRON_ORE'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('IRON_INGOT'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('IRON_PLATES'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('SCREWS'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('LOG'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(asset('PLANK'), 5, 0, 64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
-- (asset('BLUEPRINT_DEMO_HOUSE'), 3, 0, 1, NULL, NULL, NULL, asset('BLUEPRINT'), NULL, NULL, 4, 4, ''),
|
||||
(asset('CREATURE_FOOD'), 5, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
@ -1 +0,0 @@
|
|||
Only modify these for eco2d game specifically!
|
|
@ -1,18 +0,0 @@
|
|||
INSERT INTO recipes (product, product_qty, process_ticks, producer) VALUES
|
||||
(asset('IRON_PLATES'), 4, 20, asset('FURNACE')),
|
||||
(asset('SCREWS'), 8, 40, asset('CRAFTBENCH')),
|
||||
(asset('BELT'), 1, 120, asset('ASSEMBLER'));
|
||||
|
||||
INSERT INTO reagents (asset_id, qty) VALUES
|
||||
(asset('IRON_ORE'), 1),
|
||||
(asset('IRON_PLATES'), 1),
|
||||
(asset('FENCE'), 1),
|
||||
(asset('SCREWS'), 4),
|
||||
(asset('IRON_PLATES'), 2);
|
||||
|
||||
INSERT INTO recipe_reagents (recipe_id, reagent_id) VALUES
|
||||
(1, 1),
|
||||
(2, 2),
|
||||
(3, 3),
|
||||
(3, 4),
|
||||
(3, 5);
|
|
@ -1,42 +0,0 @@
|
|||
INSERT INTO resources (asset, kind) VALUES
|
||||
(asset('EMPTY'), 0),
|
||||
(asset('BLANK'), 0),
|
||||
(asset('BLOCK_FRAME'), 0),
|
||||
(asset('BUILDMODE_HIGHLIGHT'), 0),
|
||||
(asset('COAL'), 0),
|
||||
(asset('IRON_ORE'), 0),
|
||||
(asset('IRON_INGOT'), 0),
|
||||
(asset('IRON_PLATES'), 0),
|
||||
(asset('SCREWS'), 0),
|
||||
(asset('LOG'), 0),
|
||||
(asset('PLANK'), 0),
|
||||
(asset('CHEST'), 0),
|
||||
(asset('CREATURE'), 0),
|
||||
(asset('CREATURE_FOOD'), 0),
|
||||
(asset('FURNACE'), 0),
|
||||
(asset('SPLITTER'), 0),
|
||||
(asset('ASSEMBLER'), 0),
|
||||
(asset('CRAFTBENCH'), 0),
|
||||
(asset('BLUEPRINT'), 0),
|
||||
(asset('BLUEPRINT_DEMO_HOUSE'), 0),
|
||||
(asset('MOB'), 0),
|
||||
(asset('PLAYER'), 0),
|
||||
(asset('FENCE'), 0),
|
||||
(asset('DEV'), 0),
|
||||
(asset('GROUND'), 0),
|
||||
(asset('DIRT'), 0),
|
||||
(asset('WATER'), 2),
|
||||
(asset('LAVA'), 0),
|
||||
(asset('WALL'), 0),
|
||||
(asset('HILL'), 0),
|
||||
(asset('HILL_SNOW'), 0),
|
||||
(asset('HOLE'), 0),
|
||||
(asset('WOOD'), 0),
|
||||
(asset('TEST_TALL'), 0),
|
||||
(asset('TREE'), 0),
|
||||
(asset('BELT'), 0),
|
||||
(asset('BELT_LEFT'), 0),
|
||||
(asset('BELT_RIGHT'), 0),
|
||||
(asset('BELT_UP'), 0),
|
||||
(asset('BELT_DOWN'), 0);
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
CREATE TABLE assets (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(255) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE resources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
asset INTEGER NOT NULL,
|
||||
kind INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE blocks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
kind INTEGER NOT NULL,
|
||||
flags INTEGER DEFAULT 0,
|
||||
drag REAL,
|
||||
friction REAL,
|
||||
bounce REAL,
|
||||
velx REAL,
|
||||
vely REAL,
|
||||
FOREIGN KEY (kind) REFERENCES assets(id)
|
||||
);
|
||||
|
||||
CREATE TABLE items (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
kind INTEGER NOT NULL,
|
||||
usage INTEGER,
|
||||
attachment INTEGER,
|
||||
max_quantity INTEGER,
|
||||
has_storage BOOLEAN,
|
||||
|
||||
place_kind INTEGER,
|
||||
directional BOOLEAN,
|
||||
|
||||
proxy_id INTEGER,
|
||||
|
||||
place_item_id INTEGER,
|
||||
|
||||
producer INTEGER,
|
||||
energy_level REAL,
|
||||
|
||||
blueprint_w INTEGER,
|
||||
blueprint_h INTEGER,
|
||||
blueprint_plan TEXT,
|
||||
|
||||
FOREIGN KEY (kind) REFERENCES assets(id)
|
||||
);
|
||||
|
||||
CREATE TABLE reagents (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
asset_id INTEGER NOT NULL,
|
||||
qty INTEGER NOT NULL,
|
||||
FOREIGN KEY (asset_id) REFERENCES assets(id)
|
||||
);
|
||||
|
||||
CREATE TABLE recipes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
product INTEGER NOT NULL,
|
||||
product_qty INTEGER NOT NULL,
|
||||
process_ticks INTEGER NOT NULL,
|
||||
producer INTEGER NOT NULL,
|
||||
FOREIGN KEY (product) REFERENCES assets(id),
|
||||
FOREIGN KEY (producer) REFERENCES assets(id)
|
||||
);
|
||||
|
||||
CREATE TABLE recipe_reagents (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
recipe_id INTEGER NOT NULL,
|
||||
reagent_id INTEGER NOT NULL,
|
||||
FOREIGN KEY (recipe_id) REFERENCES recipes(id),
|
||||
FOREIGN KEY (reagent_id) REFERENCES reagents(id)
|
||||
);
|
Before Width: | Height: | Size: 24 KiB |
|
@ -1,3 +0,0 @@
|
|||
@echo off
|
||||
call win\setup_cl_generic.bat amd64
|
||||
cmake --build build && build\eco2d
|
|
@ -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()
|
||||
|
|
|
@ -8,12 +8,6 @@ function(link_system_libs target_name)
|
|||
elseif (UNIX)
|
||||
target_link_libraries(${target_name} pthread m dl atomic)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_compile_options(${target_name} PRIVATE -WX -W3 -wd5105)
|
||||
else()
|
||||
target_compile_options(${target_name} PRIVATE -Werror -Wall -Wextra -Wno-unused-function -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-parameter)
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
macro(use_cxx11)
|
||||
|
|
|
@ -3,29 +3,21 @@ file(GLOB PKT_SRCS src/packets/*.h src/packets/*.c)
|
|||
add_library(eco2d-foundation STATIC
|
||||
src/core/game.c
|
||||
src/core/camera.c
|
||||
src/core/rules_default.c
|
||||
|
||||
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/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/ents/items.c
|
||||
src/ents/entity.c
|
||||
src/ents/player.c
|
||||
src/ents/vehicle.c
|
||||
src/ents/storage.c
|
||||
src/ents/device.c
|
||||
|
||||
src/pkt/packet.c
|
||||
|
||||
src/gen/texgen_fallback.c
|
||||
|
||||
src/dev/debug_ui.c
|
||||
src/dev/debug_draw.c
|
||||
src/debug/debug_ui.c
|
||||
src/debug/debug_draw.c
|
||||
|
||||
src/utils/options.c
|
||||
src/utils/compress.c
|
||||
|
@ -38,14 +30,20 @@ add_library(eco2d-foundation STATIC
|
|||
src/world/world_view.c
|
||||
src/world/entity_view.c
|
||||
src/world/prediction.c
|
||||
src/world/worldgen/worldgen_test.c
|
||||
|
||||
src/systems/systems.c
|
||||
src/gen/assets.c
|
||||
src/gen/texgen.c
|
||||
|
||||
src/ecs/systems.c
|
||||
src/ecs/components.c
|
||||
|
||||
${PKT_SRCS}
|
||||
)
|
||||
|
||||
target_compile_definitions(eco2d-foundation PRIVATE CLIENT)
|
||||
include_directories(src ../modules ../../art/gen)
|
||||
target_link_libraries(eco2d-foundation raylib raylib_nuklear cwpack flecs-bundle vendors-bundle)
|
||||
target_link_libraries(eco2d-foundation raylib cwpack flecs-bundle vendors-bundle)
|
||||
target_compile_options(eco2d-foundation PRIVATE -Werror -Wall -Wextra -Wno-unused-function -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-parameter)
|
||||
|
||||
link_system_libs(eco2d-foundation)
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define ASSET_INVALID 0xFF
|
||||
|
||||
#define _ASSETS\
|
||||
X(ASSET_EMPTY)\
|
||||
X(ASSET_BLANK)\
|
||||
X(ASSET_BLOCK_FRAME)\
|
||||
X(ASSET_BUILDMODE_HIGHLIGHT)\
|
||||
X(ASSET_PLAYER)\
|
||||
X(ASSET_THING)\
|
||||
X(ASSET_CREATURE)\
|
||||
X(ASSET_CREATURE_FOOD)\
|
||||
X(ASSET_CHEST)\
|
||||
X(ASSET_SPLITTER)\
|
||||
X(ASSET_ASSEMBLER)\
|
||||
X(ASSET_FURNACE)\
|
||||
X(ASSET_CRAFTBENCH)\
|
||||
X(ASSET_BLUEPRINT_BEGIN)\
|
||||
X(ASSET_BLUEPRINT)\
|
||||
X(ASSET_BLUEPRINT_DEMO_HOUSE)\
|
||||
X(ASSET_BLUEPRINT_END)\
|
||||
X(ASSET_FENCE)\
|
||||
X(ASSET_DEV)\
|
||||
X(ASSET_GROUND)\
|
||||
X(ASSET_DIRT)\
|
||||
X(ASSET_WATER)\
|
||||
X(ASSET_LAVA)\
|
||||
X(ASSET_WALL)\
|
||||
X(ASSET_HILL)\
|
||||
X(ASSET_HILL_SNOW)\
|
||||
X(ASSET_HOLE)\
|
||||
X(ASSET_WOOD)\
|
||||
X(ASSET_TREE)\
|
||||
X(ASSET_COAL)\
|
||||
X(ASSET_IRON_ORE)\
|
||||
X(ASSET_IRON_INGOT)\
|
||||
X(ASSET_IRON_PLATES)\
|
||||
X(ASSET_SCREWS)\
|
||||
X(ASSET_LOG)\
|
||||
X(ASSET_PLANK)\
|
||||
X(ASSET_TEST_TALL)\
|
||||
X(ASSET_BELT)\
|
||||
X(ASSET_BELT_LEFT)\
|
||||
X(ASSET_BELT_RIGHT)\
|
||||
X(ASSET_BELT_UP)\
|
||||
X(ASSET_BELT_DOWN)
|
||||
|
||||
typedef enum {
|
||||
#define X(idx) idx,
|
||||
_ASSETS
|
||||
#undef X
|
||||
MAX_INTERNAL_ASSETS,
|
||||
NEXT_FREE_ASSET = MAX_INTERNAL_ASSETS,
|
||||
MAX_ASSETS = 255
|
||||
} asset_id;
|
||||
|
||||
extern const char *asset_names[];
|
|
@ -3,44 +3,36 @@
|
|||
#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"
|
||||
#include "ents/entity.h"
|
||||
#include "ents/items.h"
|
||||
#include "world/world_view.h"
|
||||
#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"
|
||||
#include "flecs/flecs.h"
|
||||
|
||||
#include "models/components.h"
|
||||
#include "systems/systems.h"
|
||||
#include "ecs/components.h"
|
||||
#include "ecs/systems.h"
|
||||
|
||||
#include "packets/pkt_00_init.h"
|
||||
#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);
|
||||
header.udata = udata;
|
||||
|
||||
|
||||
if (ok && header.ok) {
|
||||
return pkt_handlers[header.id].handler(&header) >= 0;
|
||||
} else {
|
||||
|
@ -75,7 +67,7 @@ static WORLD_PKT_WRITER(mp_cli_pkt_writer) {
|
|||
|
||||
void world_viewers_init(uint32_t num_viewers) {
|
||||
zpl_buffer_init(world_viewers, zpl_heap(), num_viewers);
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < num_viewers; i++) {
|
||||
zpl_buffer_append(world_viewers, world_view_create(i));
|
||||
}
|
||||
|
@ -101,7 +93,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 < zpl_buffer_count(world_viewers));
|
||||
ZPL_ASSERT(idx >= 0 && idx < zpl_buffer_count(world_viewers));
|
||||
game_world_view_set_active(&world_viewers[idx]);
|
||||
}
|
||||
|
||||
|
@ -134,40 +126,42 @@ float game_time() {
|
|||
return (float)get_cached_time();
|
||||
}
|
||||
|
||||
void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) {
|
||||
void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) {
|
||||
game_mode = play_mode;
|
||||
game_should_close = false;
|
||||
|
||||
entity_default_spawnlist();
|
||||
game_init(db_init());
|
||||
|
||||
#ifndef _DEBUG
|
||||
const char *host_ip = "lab.zakto.pw";
|
||||
#else
|
||||
const char *host_ip = "127.0.0.1";
|
||||
#endif
|
||||
|
||||
|
||||
uint16_t host_port = (port > 0) ? port : 27000;
|
||||
|
||||
|
||||
if (ip != NULL) {
|
||||
host_ip = ip;
|
||||
}
|
||||
|
||||
|
||||
// NOTE: initialise subsystems
|
||||
{
|
||||
assets_setup();
|
||||
blocks_setup();
|
||||
item_setup();
|
||||
entity_spawndef_setup();
|
||||
}
|
||||
|
||||
if (game_mode != GAMEKIND_HEADLESS) {
|
||||
platform_init();
|
||||
|
||||
|
||||
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) {
|
||||
network_init();
|
||||
}
|
||||
|
||||
|
||||
if (game_mode == GAMEKIND_CLIENT) {
|
||||
world_setup_pkt_handlers(pkt_reader, mp_cli_pkt_writer);
|
||||
network_client_connect(host_ip, host_port);
|
||||
|
@ -176,15 +170,13 @@ void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num
|
|||
world_setup_pkt_handlers(pkt_reader, game_mode == GAMEKIND_SINGLE ? sp_pkt_writer : mp_pkt_writer);
|
||||
world_init(seed, chunk_size, chunk_amount);
|
||||
if (is_dash_enabled) flecs_dash_init();
|
||||
|
||||
|
||||
if (game_mode == GAMEKIND_HEADLESS) {
|
||||
network_server_start(0, 27000);
|
||||
//ecs_set_target_fps(world_ecs(), 60);
|
||||
}
|
||||
}
|
||||
|
||||
game_init_ecs();
|
||||
|
||||
if (game_mode == GAMEKIND_SINGLE) {
|
||||
for (uint32_t i = 0; i < num_viewers; i++) {
|
||||
pkt_00_init_send(i);
|
||||
|
@ -197,29 +189,35 @@ int8_t game_is_networked() {
|
|||
}
|
||||
|
||||
void game_shutdown() {
|
||||
db_shutdown();
|
||||
|
||||
|
||||
if (game_mode == GAMEKIND_CLIENT) {
|
||||
network_client_disconnect();
|
||||
} else {
|
||||
world_destroy();
|
||||
|
||||
|
||||
if (game_mode == GAMEKIND_HEADLESS) {
|
||||
network_server_stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (game_mode != GAMEKIND_SINGLE) {
|
||||
network_destroy();
|
||||
}
|
||||
|
||||
|
||||
if (game_mode != GAMEKIND_HEADLESS) {
|
||||
world_viewers_destroy();
|
||||
|
||||
|
||||
// TODO(zaklaus): crashes on exit
|
||||
//platform_shutdown();
|
||||
UnloadNuklear(game_ui);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: shutdown subsystems
|
||||
{
|
||||
item_cleanup();
|
||||
entity_spawndef_cleanup();
|
||||
blocks_cleanup();
|
||||
assets_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t game_is_running() {
|
||||
|
@ -234,24 +232,23 @@ game_kind game_get_kind(void) {
|
|||
return game_mode;
|
||||
}
|
||||
|
||||
void game_core_input() {
|
||||
void game_input() {
|
||||
if (game_mode != GAMEKIND_HEADLESS) {
|
||||
platform_input();
|
||||
UpdateNuklear(game_ui);
|
||||
}
|
||||
}
|
||||
|
||||
void game_core_update() {
|
||||
void game_update() {
|
||||
static double last_update = 0.0f;
|
||||
if (game_mode == GAMEKIND_CLIENT) {
|
||||
network_client_tick();
|
||||
}
|
||||
else {
|
||||
world_update();
|
||||
|
||||
|
||||
if (game_mode == GAMEKIND_HEADLESS) {
|
||||
network_server_tick();
|
||||
|
||||
|
||||
static float ms_report = 2.5f;
|
||||
if (ms_report < get_cached_time()) {
|
||||
ms_report = get_cached_time() + 5.f;
|
||||
|
@ -259,20 +256,16 @@ void game_core_update() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
last_update = get_cached_time();
|
||||
}
|
||||
|
||||
void game_core_render() {
|
||||
void game_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);
|
||||
}
|
||||
|
@ -291,71 +284,3 @@ 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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#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,
|
||||
|
@ -11,7 +10,7 @@ typedef enum {
|
|||
FORCE_GAMEKIND_UINT8 = UINT8_MAX
|
||||
} game_kind;
|
||||
|
||||
void game_setup(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled);
|
||||
void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled);
|
||||
void game_shutdown();
|
||||
void game_request_close();
|
||||
uint8_t game_is_running();
|
||||
|
@ -20,24 +19,9 @@ 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);
|
||||
|
@ -48,7 +32,6 @@ void game_world_view_set_active(world_view *view);
|
|||
void game_world_view_cycle_active(int8_t dir);
|
||||
void game_world_view_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);
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
#pragma once
|
||||
#include "platform/system.h"
|
||||
|
||||
typedef struct {
|
||||
float phy_walk_drag;
|
||||
uint64_t demo_npc_move_speed;
|
||||
uint64_t demo_npc_steer_speed;
|
||||
float item_pick_radius;
|
||||
float item_merger_radius;
|
||||
float item_attract_radius;
|
||||
float item_attract_force;
|
||||
float item_container_reach_radius;
|
||||
float item_drop_pickup_time;
|
||||
float item_drop_merger_time;
|
||||
float plr_move_speed;
|
||||
float plr_move_speed_mult;
|
||||
float vehicle_force;
|
||||
float vehicle_accel;
|
||||
float vehicle_decel;
|
||||
float vehicle_steer;
|
||||
float vehicle_steer_compensation;
|
||||
float vehicle_steer_revert;
|
||||
float vehicle_power;
|
||||
float vehicle_brake_force;
|
||||
float veh_enter_radius;
|
||||
float blueprint_build_time;
|
||||
|
||||
// survival rules
|
||||
} game_rulesdef;
|
||||
|
||||
extern game_rulesdef game_rules;
|
||||
|
||||
void rules_setup();
|
|
@ -1,26 +0,0 @@
|
|||
#include "core/rules.h"
|
||||
|
||||
game_rulesdef game_rules = {
|
||||
.phy_walk_drag = 4.23f,
|
||||
.demo_npc_move_speed = 500,
|
||||
.demo_npc_steer_speed = 300,
|
||||
.item_pick_radius = 25.0f,
|
||||
.item_merger_radius = 75.0f,
|
||||
.item_attract_radius = 75.0f,
|
||||
.item_attract_force = 1.98f,
|
||||
.item_container_reach_radius = 105.0f,
|
||||
.item_drop_pickup_time = 2.5f,
|
||||
.item_drop_merger_time = 6.5f,
|
||||
.plr_move_speed = 800.0f,
|
||||
.plr_move_speed_mult = 1.5f,
|
||||
.vehicle_force = 240.8f,
|
||||
.vehicle_accel = 0.032f,
|
||||
.vehicle_decel = 0.28f,
|
||||
.vehicle_steer = 35.89f,
|
||||
.vehicle_steer_compensation = 4.0f,
|
||||
.vehicle_steer_revert = 6.0941816f,
|
||||
.vehicle_power = 97.89f,
|
||||
.vehicle_brake_force = 0.84f,
|
||||
.veh_enter_radius = 45.0f,
|
||||
.blueprint_build_time = 1.5f,
|
||||
};
|
|
@ -1,9 +1,9 @@
|
|||
#include "dev/debug_draw.h"
|
||||
#include "debug/debug_draw.h"
|
||||
#include "core/game.h"
|
||||
|
||||
static debug_draw_queue draw_queue = {0};
|
||||
|
||||
#if !defined(_DEBUG) || 0
|
||||
#ifndef _DEBUG
|
||||
static bool draw_is_enabled = false;
|
||||
#else
|
||||
static bool draw_is_enabled = true;
|
|
@ -1,17 +1,20 @@
|
|||
#include "dev/debug_replay.h"
|
||||
#include "debug/debug_replay.h"
|
||||
#include "core/camera.h"
|
||||
#include "models/entity.h"
|
||||
#include "ents/entity.h"
|
||||
|
||||
#include "cwpack/cwpack.h"
|
||||
|
||||
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 {
|
||||
|
@ -42,17 +45,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);
|
||||
|
@ -61,44 +64,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;
|
||||
|
@ -109,10 +112,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);
|
||||
}
|
||||
|
@ -127,17 +130,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);
|
||||
}
|
||||
|
||||
|
@ -154,17 +157,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);
|
||||
}
|
||||
|
@ -172,17 +175,17 @@ void debug_replay_run(void) {
|
|||
void ActPlaceIceRink(void);
|
||||
void ActSpawnCirclingDriver(void);
|
||||
void ActEraseWorldChanges(void);
|
||||
void ActSpawnCoal(void);
|
||||
void ActSpawnIcemaker(void);
|
||||
void ActSpawnChest(void);
|
||||
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);
|
||||
|
@ -205,12 +208,12 @@ void debug_replay_update(void) {
|
|||
}
|
||||
}break;
|
||||
case RPKIND_SPAWN_CAR: {
|
||||
ecs_entity_t e = vehicle_spawn(EVEH_CAR);
|
||||
|
||||
ecs_entity_t e = vehicle_spawn();
|
||||
|
||||
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: {
|
||||
|
@ -222,13 +225,22 @@ void debug_replay_update(void) {
|
|||
case RPKIND_PLACE_ERASE_CHANGES:{
|
||||
ActEraseWorldChanges();
|
||||
}break;
|
||||
case RPKIND_SPAWN_ICEMAKER_ITEM:{
|
||||
ActSpawnIcemaker();
|
||||
}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();
|
||||
|
@ -238,13 +250,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();
|
||||
}
|
||||
|
@ -253,12 +265,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();
|
||||
}
|
|
@ -1,17 +1,13 @@
|
|||
#include "dev/debug_ui.h"
|
||||
#include "dev/debug_draw.h"
|
||||
#include "debug/debug_ui.h"
|
||||
#include "debug/debug_draw.h"
|
||||
#include "raylib.h"
|
||||
#include "models/prefabs/vehicle.h"
|
||||
#include "ents/vehicle.h"
|
||||
#include "core/camera.h"
|
||||
#include "world/world.h"
|
||||
#include "core/game.h"
|
||||
#include "sfd.h"
|
||||
|
||||
#include "models/components.h"
|
||||
|
||||
ZPL_DIAGNOSTIC_PUSH_WARNLEVEL(0)
|
||||
#include "raylib-nuklear.h"
|
||||
ZPL_DIAGNOSTIC_POP
|
||||
#include "ecs/components.h"
|
||||
|
||||
typedef enum {
|
||||
DITEM_RAW,
|
||||
|
@ -20,11 +16,9 @@ typedef enum {
|
|||
DITEM_BUTTON,
|
||||
DITEM_SLIDER,
|
||||
DITEM_LIST,
|
||||
DITEM_TOOL,
|
||||
DITEM_COND,
|
||||
|
||||
DITEM_END,
|
||||
|
||||
|
||||
DITEM_FORCE_UINT8 = UINT8_MAX
|
||||
} debug_kind;
|
||||
|
||||
|
@ -47,8 +41,6 @@ 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,
|
||||
|
@ -62,58 +54,48 @@ typedef struct debug_item {
|
|||
float name_width;
|
||||
uint8_t skip;
|
||||
limit_kind limit_to;
|
||||
|
||||
|
||||
union {
|
||||
union {
|
||||
char const *text;
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
|
||||
struct {
|
||||
struct debug_item *items;
|
||||
uint8_t is_collapsed;
|
||||
} list;
|
||||
|
||||
|
||||
struct {
|
||||
float val, min, max;
|
||||
void (*on_change)(float);
|
||||
} slider;
|
||||
|
||||
struct {
|
||||
uint8_t is_open;
|
||||
void (*on_draw)(void);
|
||||
} tool;
|
||||
|
||||
|
||||
void (*on_click)(void);
|
||||
|
||||
|
||||
uint8_t (*on_success)(void);
|
||||
};
|
||||
|
||||
|
||||
debug_draw_result (*proc)(struct debug_item*, float, float);
|
||||
} 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 "dev/debug_replay.c"
|
||||
#include "debug/debug_replay.c"
|
||||
|
||||
#include "gui/ui_skin.c"
|
||||
|
||||
#include "dev/debug_ui_actions.c"
|
||||
#include "dev/debug_ui_widgets.c"
|
||||
#include "dev/debug_ui_tools.c"
|
||||
#include "debug/debug_ui_actions.c"
|
||||
#include "debug/debug_ui_widgets.c"
|
||||
|
||||
static debug_item items[] = {
|
||||
{
|
||||
.kind = DITEM_LIST,
|
||||
.name = "general",
|
||||
.kind = DITEM_LIST,
|
||||
.name = "general",
|
||||
.list = {
|
||||
.is_collapsed = true,
|
||||
.items = (debug_item[]) {
|
||||
{ .kind = DITEM_TEXT, .name = "delta time", .proc = DrawDeltaTime },
|
||||
{ .kind = DITEM_TEXT, .name = "camera pos", .proc = DrawCameraPos },
|
||||
{ .kind = DITEM_TEXT, .name = "mouse block", .proc = DrawBlockPos },
|
||||
{ .kind = DITEM_TEXT, .name = "mouse chunk", .proc = DrawChunkPos },
|
||||
{ .kind = DITEM_TEXT, .name = "pos", .proc = DrawCameraPos },
|
||||
{ .kind = DITEM_TEXT, .name = "zoom", .proc = DrawZoom },
|
||||
{ .kind = DITEM_END },
|
||||
}
|
||||
|
@ -127,17 +109,17 @@ static debug_item items[] = {
|
|||
.items = (debug_item[]) {
|
||||
{ .kind = DITEM_COND, .on_success = CondIsWorldRunning },
|
||||
{ .kind = DITEM_BUTTON, .name = "pause", .on_click = ActWorldToggleSim },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondIsWorldPaused, .skip = 6 },
|
||||
{ .kind = DITEM_BUTTON, .name = "resume", .on_click = ActWorldToggleSim },
|
||||
|
||||
|
||||
{ .kind = DITEM_GAP },
|
||||
|
||||
|
||||
{ .kind = DITEM_TEXT, .name = "step size", .proc = DrawWorldStepSize },
|
||||
{ .kind = DITEM_BUTTON, .name = "single-step", .on_click = ActWorldStep },
|
||||
{ .kind = DITEM_BUTTON, .name = "increment step size", .on_click = ActWorldIncrementSimStepSize },
|
||||
{ .kind = DITEM_BUTTON, .name = "decrement step size", .on_click = ActWorldDecrementSimStepSize },
|
||||
|
||||
|
||||
{ .kind = DITEM_END },
|
||||
},
|
||||
},
|
||||
|
@ -149,25 +131,14 @@ static debug_item items[] = {
|
|||
.list = {
|
||||
.is_collapsed = true,
|
||||
.items = (debug_item[]) {
|
||||
{
|
||||
.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 = "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 icemaker item", .on_click = ActSpawnIcemaker },
|
||||
{ .kind = DITEM_BUTTON, .name = "spawn chest", .on_click = ActSpawnChest },
|
||||
{ .kind = DITEM_BUTTON, .name = "spawn belt", .on_click = ActSpawnBelt },
|
||||
{
|
||||
.kind = DITEM_LIST,
|
||||
.name = "demo npcs",
|
||||
.list = {
|
||||
|
@ -193,13 +164,13 @@ static debug_item items[] = {
|
|||
.items = (debug_item[]) {
|
||||
{ .kind = DITEM_COND, .on_success = CondClientDisconnected },
|
||||
{ .kind = DITEM_TEXT, .name = "status", .proc = DrawLiteral, .text = "disconnected" },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondClientConnected },
|
||||
{ .kind = DITEM_TEXT, .name = "status", .proc = DrawLiteral, .text = "connected" },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondClientConnected },
|
||||
{ .kind = DITEM_TEXT, .proc = DrawNetworkStats },
|
||||
|
||||
|
||||
{ .kind = DITEM_END },
|
||||
},
|
||||
},
|
||||
|
@ -213,30 +184,30 @@ static debug_item items[] = {
|
|||
.items = (debug_item[]) {
|
||||
{ .kind = DITEM_TEXT, .name = "macro", .proc = DrawReplayFileName },
|
||||
{ .kind = DITEM_TEXT, .name = "samples", .proc = DrawReplaySamples },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondReplayDataPresentAndNotPlaying },
|
||||
{ .kind = DITEM_BUTTON, .name = "replay", .on_click = ActReplayRun },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondReplayStatusOff },
|
||||
{ .kind = DITEM_BUTTON, .name = "record", .on_click = ActReplayBegin },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondReplayStatusOn },
|
||||
{ .kind = DITEM_BUTTON, .name = "stop", .on_click = ActReplayEnd },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondReplayIsPlaying },
|
||||
{ .kind = DITEM_BUTTON, .name = "stop", .on_click = ActReplayEnd },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondReplayIsNotPlayingOrRecordsNotClear },
|
||||
{ .kind = DITEM_BUTTON, .name = "clear", .on_click = ActReplayClear },
|
||||
|
||||
|
||||
{ .kind = DITEM_GAP },
|
||||
|
||||
|
||||
{ .kind = DITEM_COND, .on_success = CondReplayIsNotPlaying, .skip = 4 },
|
||||
{ .kind = DITEM_BUTTON, .name = "new", .on_click = ActReplayNew },
|
||||
{ .kind = DITEM_BUTTON, .name = "load", .on_click = ActReplayLoad },
|
||||
{ .kind = DITEM_BUTTON, .name = "save", .on_click = ActReplaySave },
|
||||
{ .kind = DITEM_BUTTON, .name = "save as...", .on_click = ActReplaySaveAs },
|
||||
|
||||
|
||||
{ .kind = DITEM_END },
|
||||
},
|
||||
.is_collapsed = true,
|
||||
|
@ -255,27 +226,12 @@ 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_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_RAW, .val = PROF_INTEGRATE_POS, .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,
|
||||
|
@ -297,7 +253,7 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
|
|||
}break;
|
||||
case DITEM_COND: {
|
||||
ZPL_ASSERT(it->on_success);
|
||||
|
||||
|
||||
if (!it->on_success()) {
|
||||
it += it->skip ? it->skip : 1;
|
||||
}
|
||||
|
@ -311,15 +267,15 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
|
|||
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color)) {
|
||||
it->list.is_collapsed = !it->list.is_collapsed;
|
||||
}
|
||||
|
||||
|
||||
UIDrawText(it->name, xpos, ypos, DBG_FONT_SIZE, color);
|
||||
ypos += DBG_FONT_SPACING;
|
||||
if (it->list.is_collapsed) break;
|
||||
|
||||
|
||||
debug_draw_result res = debug_draw_list(it->list.items, xpos+DBG_LIST_XPOS_OFFSET, ypos, is_shadow);
|
||||
ypos = res.y;
|
||||
}break;
|
||||
|
||||
|
||||
case DITEM_TEXT: {
|
||||
if (it->name) {
|
||||
char const *text = TextFormat("%s: ", it->name);
|
||||
|
@ -329,18 +285,18 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
|
|||
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, RAYWHITE);
|
||||
ZPL_ASSERT(it->proc);
|
||||
}
|
||||
|
||||
|
||||
debug_draw_result res = it->proc(it, xpos + it->name_width, ypos);
|
||||
ypos = res.y;
|
||||
}break;
|
||||
|
||||
|
||||
case DITEM_RAW: {
|
||||
ZPL_ASSERT(it->proc);
|
||||
|
||||
|
||||
debug_draw_result res = it->proc(it, xpos, ypos);
|
||||
ypos = res.y;
|
||||
}break;
|
||||
|
||||
|
||||
case DITEM_BUTTON: {
|
||||
char const *text = TextFormat("> %s", it->name);
|
||||
if (it->name_width == 0) {
|
||||
|
@ -350,15 +306,15 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
|
|||
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color) && it->on_click) {
|
||||
it->on_click();
|
||||
}
|
||||
|
||||
|
||||
if (!it->on_click) {
|
||||
color = GRAY;
|
||||
}
|
||||
|
||||
|
||||
debug_draw_result res = DrawColoredText(xpos, ypos, text, color);
|
||||
ypos = res.y;
|
||||
}break;
|
||||
|
||||
|
||||
case DITEM_SLIDER: {
|
||||
ZPL_ASSERT(it->slider.min != it->slider.max);
|
||||
char const *text = TextFormat("%s: ", it->name);
|
||||
|
@ -367,65 +323,33 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
|
|||
}
|
||||
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, RAYWHITE);
|
||||
xpos += it->name_width;
|
||||
|
||||
|
||||
DrawRectangleLines((int)xpos, (int)ypos, 100, DBG_FONT_SIZE, RAYWHITE);
|
||||
|
||||
|
||||
float stick_x = xpos + ((it->slider.val / it->slider.max) * 100.0f) - 5.0f;
|
||||
DrawRectangle((int)stick_x, (int)ypos, 10, DBG_FONT_SIZE, RED);
|
||||
|
||||
|
||||
xpos += 100.0f + 5.0f;
|
||||
DrawFloat(xpos, ypos, it->slider.val);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (debug_draw_result){xpos, ypos};
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
// NOTE(zaklaus): move debug ui
|
||||
{
|
||||
debug_area_status area = check_mouse_area(xpos, ypos, DBG_CTRL_HANDLE_DIM, DBG_CTRL_HANDLE_DIM);
|
||||
|
@ -435,19 +359,19 @@ void debug_draw(void) {
|
|||
color = RED;
|
||||
is_handle_ctrl_held = 1;
|
||||
}
|
||||
|
||||
|
||||
if (is_handle_ctrl_held) {
|
||||
debug_xpos = xpos = (float)(GetMouseX() - DBG_CTRL_HANDLE_DIM/2);
|
||||
debug_ypos = ypos = (float)(GetMouseY() - DBG_CTRL_HANDLE_DIM/2);
|
||||
|
||||
|
||||
if (area == DAREA_PRESS) {
|
||||
is_handle_ctrl_held = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DrawRectangle((int)xpos, (int)ypos, DBG_CTRL_HANDLE_DIM, DBG_CTRL_HANDLE_DIM, color);
|
||||
}
|
||||
|
||||
|
||||
// NOTE(zaklaus): toggle debug ui
|
||||
{
|
||||
Color color = BLUE;
|
||||
|
@ -461,20 +385,18 @@ void debug_draw(void) {
|
|||
}
|
||||
DrawPoly((Vector2){xpos+DBG_CTRL_HANDLE_DIM/2, ypos+15+DBG_CTRL_HANDLE_DIM/2}, 3, 6.0f,is_debug_open ? 0.0f : 180.0f, color);
|
||||
}
|
||||
|
||||
|
||||
if (is_debug_open) {
|
||||
xpos += 15;
|
||||
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) {
|
||||
if (is_shadow_rendered) return DAREA_OUTSIDE;
|
||||
bool is_inside = CheckCollisionPointRec(GetMousePosition(), (Rectangle){xpos, ypos, w, h});
|
||||
|
||||
|
||||
if (is_inside) {
|
||||
return IsMouseButtonReleased(MOUSE_LEFT_BUTTON) ? DAREA_PRESS : IsMouseButtonDown(MOUSE_LEFT_BUTTON) ? DAREA_HELD : DAREA_HOVER;
|
||||
}
|
||||
|
@ -493,34 +415,34 @@ bool is_btn_pressed(float xpos, float ypos, float w, float h, Color *color) {
|
|||
} else if (area == DAREA_HELD) {
|
||||
*color = RED;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline
|
||||
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 = 10; // Default Font chars height in pixel
|
||||
int new_spacing = fontSize/defaultFontSize;
|
||||
|
||||
|
||||
DrawTextEx(GetFontDefault(), text, position, (float)fontSize , (float)new_spacing , is_shadow_rendered ? BLACK : color);
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
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;
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
#include "dev/debug_ui.h"
|
||||
#include "debug/debug_ui.h"
|
||||
#include "world/blocks.h"
|
||||
#include "models/items.h"
|
||||
#include "ents/items.h"
|
||||
#include "net/network.h"
|
||||
|
||||
#include "models/entity.h"
|
||||
|
||||
void
|
||||
ActExitGame(void) {
|
||||
game_request_close();
|
||||
|
@ -12,54 +10,62 @@ ActExitGame(void) {
|
|||
|
||||
void
|
||||
ActSpawnCar(void) {
|
||||
ecs_entity_t e = vehicle_spawn(EVEH_CAR);
|
||||
ecs_entity_t e = vehicle_spawn();
|
||||
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_CAR);
|
||||
}
|
||||
|
||||
void
|
||||
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
|
||||
ActSpawnItemNext(void) {
|
||||
while (true) {
|
||||
++sel_item_id;
|
||||
item_id id = item_find_no_proxy(sel_item_id);
|
||||
if (sel_item_id > 0 && id != ASSET_INVALID && (item_get_usage(id) != UKIND_PROXY)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ActSpawnSelItem(void) {
|
||||
ecs_entity_t e = item_spawn(sel_item_id, 32);
|
||||
ActSpawnIcemaker(void) {
|
||||
ecs_entity_t e = item_spawn(ASSET_DEMO_ICEMAKER, 32);
|
||||
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);
|
||||
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
||||
*dest = *origin;
|
||||
entity_set_position(e, dest->x, dest->y);
|
||||
|
||||
debug_replay_special_action(RPKIND_SPAWN_ICEMAKER_ITEM);
|
||||
}
|
||||
|
||||
void
|
||||
ActSpawnChest(void) {
|
||||
ecs_entity_t e = item_spawn(ASSET_CHEST, 32);
|
||||
ecs_entity_t plr = camera_get().ent_id;
|
||||
|
||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
||||
*dest = *origin;
|
||||
entity_set_position(e, dest->x, dest->y);
|
||||
|
||||
debug_replay_special_action(RPKIND_SPAWN_CHEST);
|
||||
}
|
||||
|
||||
void
|
||||
ActSpawnBelt(void) {
|
||||
ecs_entity_t e = item_spawn(ASSET_BELT, 999);
|
||||
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
|
||||
ActSpawnCirclingDriver(void) {
|
||||
ecs_entity_t plr = camera_get().ent_id;
|
||||
ecs_entity_t ve = vehicle_spawn(EVEH_CAR);
|
||||
ecs_entity_t ve = vehicle_spawn();
|
||||
ecs_entity_t e = entity_spawn(EKIND_DEMO_NPC);
|
||||
|
||||
|
||||
Position const *origin = ecs_get(world_ecs(), plr, Position);
|
||||
Position *veh_dest = ecs_get_mut(world_ecs(), ve, Position);
|
||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||
|
@ -67,16 +73,16 @@ ActSpawnCirclingDriver(void) {
|
|||
*dest = *origin;
|
||||
entity_set_position(ve, veh_dest->x, veh_dest->y);
|
||||
entity_set_position(e, dest->x, dest->y);
|
||||
|
||||
|
||||
Input *input = ecs_get_mut(world_ecs(), e, Input);
|
||||
zpl_zero_item(input);
|
||||
input->x = input->y = 1.0f;
|
||||
|
||||
|
||||
Vehicle *veh = ecs_get_mut(world_ecs(), ve, Vehicle);
|
||||
veh->seats[0] = e;
|
||||
|
||||
|
||||
ecs_set(world_ecs(), e, IsInVehicle, { .veh = ve });
|
||||
|
||||
|
||||
debug_replay_special_action(RPKIND_SPAWN_CIRCLING_DRIVER);
|
||||
}
|
||||
|
||||
|
@ -86,14 +92,14 @@ ActPlaceIceRink(void) {
|
|||
block_id watr_id = blocks_find(ASSET_WATER);
|
||||
Position const *p = ecs_get(world_ecs(), plr, Position);
|
||||
float const bs = WORLD_BLOCK_SIZE;
|
||||
|
||||
|
||||
for (int y = 0; y < 100; y++) {
|
||||
for (int x = 0; x < 100; x++) {
|
||||
world_block_lookup l = world_block_from_realpos((p->x - (x*bs)/2.0f), p->y - (y*bs)/2.0f);
|
||||
world_chunk_place_block(l.chunk_id, l.id, watr_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
debug_replay_special_action(RPKIND_PLACE_ICE_RINK);
|
||||
}
|
||||
|
||||
|
@ -102,13 +108,13 @@ ActEraseWorldChanges(void) {
|
|||
ecs_entity_t plr = camera_get().ent_id;
|
||||
Position const *p = ecs_get(world_ecs(), plr, Position);
|
||||
float const bs = WORLD_BLOCK_SIZE;
|
||||
|
||||
|
||||
for (int y = 0; y < 100; y++) {
|
||||
for (int x = 0; x < 100; x++) {
|
||||
world_chunk_destroy_block((p->x - (x*bs)/2.0f), (p->y - (y*bs)/2.0f), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
debug_replay_special_action(RPKIND_PLACE_ERASE_CHANGES);
|
||||
}
|
||||
|
||||
|
@ -175,22 +181,22 @@ void
|
|||
ActReplaySaveAs(void) {
|
||||
if (!records) return;
|
||||
char const *workdir = GetWorkingDirectory();
|
||||
|
||||
|
||||
sfd_Options sfd = {
|
||||
.title = "Save Macro",
|
||||
.path = "art",
|
||||
.filter_name = "eco2d Macro",
|
||||
.filter = "*.dem",
|
||||
};
|
||||
|
||||
|
||||
char const *path = sfd_save_dialog(&sfd);
|
||||
ChangeDirectory(workdir);
|
||||
|
||||
|
||||
if (path) {
|
||||
zpl_strcpy(replay_filename, zpl_bprintf("%s.dem", path));
|
||||
debug_replay_store();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -204,17 +210,17 @@ ActReplaySave(void) {
|
|||
void
|
||||
ActReplayLoad(void) {
|
||||
char const *workdir = GetWorkingDirectory();
|
||||
|
||||
|
||||
sfd_Options sfd = {
|
||||
.title = "Load Macro",
|
||||
.path = "art",
|
||||
.filter_name = "eco2d Macro",
|
||||
.filter = "*.dem",
|
||||
};
|
||||
|
||||
|
||||
char const *path = sfd_open_dialog(&sfd);
|
||||
ChangeDirectory(workdir);
|
||||
|
||||
|
||||
if (path) {
|
||||
zpl_zero_size(replay_filename, sizeof(replay_filename));
|
||||
zpl_strcpy(replay_filename, path);
|
||||
|
@ -230,17 +236,18 @@ void
|
|||
ActSpawnDemoNPCs(void) {
|
||||
if (!demo_npcs) zpl_array_init(demo_npcs, zpl_heap());
|
||||
if (zpl_array_count(demo_npcs) >= 100000) return;
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < 1000; i++) {
|
||||
uint64_t e = entity_spawn_id(ASSET_CREATURE);
|
||||
uint64_t e = entity_spawn(EKIND_DEMO_NPC);
|
||||
ecs_add(world_ecs(), e, DemoNPC);
|
||||
Position *pos = ecs_get_mut(world_ecs(), e, Position);
|
||||
pos->x=(float)(rand() % world_dim());
|
||||
pos->y=(float)(rand() % world_dim());
|
||||
|
||||
pos->y=(float)(rand() % world_dim());
|
||||
|
||||
Velocity *v = ecs_get_mut(world_ecs(), e, Velocity);
|
||||
v->x = (float)((rand()%3-1) * 10);
|
||||
v->y = (float)((rand()%3-1) * 10);
|
||||
|
||||
|
||||
zpl_array_append(demo_npcs, e);
|
||||
}
|
||||
}
|
||||
|
@ -248,9 +255,9 @@ ActSpawnDemoNPCs(void) {
|
|||
void
|
||||
ActDespawnDemoNPCs(void) {
|
||||
if (!demo_npcs) return;
|
||||
|
||||
|
||||
entity_batch_despawn(demo_npcs, zpl_array_count(demo_npcs));
|
||||
|
||||
|
||||
zpl_array_free(demo_npcs);
|
||||
demo_npcs = 0;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
#include "dev/debug_ui.h"
|
||||
#include "debug/debug_ui.h"
|
||||
#include "raylib.h"
|
||||
#include "platform/platform.h"
|
||||
#include "net/network.h"
|
||||
|
@ -6,96 +6,79 @@
|
|||
|
||||
//~ NOTE(zaklaus): helpers
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawFloat(float xpos, float ypos, float val) {
|
||||
char const *text = TextFormat("%.02f\n", val);
|
||||
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, RAYWHITE);
|
||||
return (debug_draw_result){.x = xpos + UIMeasureText(text, DBG_FONT_SIZE), .y = ypos + DBG_FONT_SPACING};
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawColoredText(float xpos, float ypos, char const *text, Color color) {
|
||||
ZPL_ASSERT(text);
|
||||
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, color);
|
||||
|
||||
|
||||
char const *p = text;
|
||||
uint8_t newlines = 1;
|
||||
|
||||
|
||||
do {
|
||||
if (*p == '\n')
|
||||
++newlines;
|
||||
} while (*p++ != 0);
|
||||
|
||||
|
||||
return (debug_draw_result){.x = xpos + UIMeasureText(text, DBG_FONT_SIZE), .y = ypos + DBG_FONT_SPACING*newlines};
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawFormattedText(float xpos, float ypos, char const *text) {
|
||||
return DrawColoredText(xpos, ypos, text, RAYWHITE);
|
||||
}
|
||||
|
||||
//~ NOTE(zaklaus): widgets
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawCameraPos(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
camera cam = camera_get();
|
||||
return DrawFormattedText(xpos, ypos, TextFormat("%d %d", (int)(cam.x/WORLD_BLOCK_SIZE), (int)(cam.y/WORLD_BLOCK_SIZE)));
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
DrawChunkPos(debug_item *it, float xpos, float ypos) {
|
||||
float mx, my;
|
||||
platform_get_block_realpos(&mx, &my);
|
||||
int csize = world_chunk_size();
|
||||
|
||||
return DrawFormattedText(xpos, ypos, TextFormat("%d %d", (int)(mx/WORLD_BLOCK_SIZE/csize), (int)(my/WORLD_BLOCK_SIZE/csize)));
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
DrawBlockPos(debug_item *it, float xpos, float ypos) {
|
||||
float mx, my;
|
||||
platform_get_block_realpos(&mx, &my);
|
||||
|
||||
return DrawFormattedText(xpos, ypos, TextFormat("%d %d", (int)(mx/WORLD_BLOCK_SIZE), (int)(my/WORLD_BLOCK_SIZE)));
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawUnmeasuredTime(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
float total_time = (float)profiler_delta(PROF_TOTAL_TIME);
|
||||
float acc_time = (float)profiler_delta(PROF_MAIN_LOOP);
|
||||
|
||||
|
||||
return DrawFormattedText(xpos, ypos, TextFormat("%.02f ms", (total_time-acc_time) * 1000.0f));
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawDeltaTime(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
float dt = GetFrameTime();
|
||||
return DrawFormattedText(xpos, ypos, TextFormat("%.02f (%.02f fps)", dt * 1000.0f, 1.0f/dt));
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawZoom(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
|
||||
|
||||
return DrawFloat(xpos, ypos, platform_zoom_get());
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawLiteral(debug_item *it, float xpos, float ypos) {
|
||||
ZPL_ASSERT(it->text);
|
||||
return DrawFormattedText(xpos, ypos, it->text);
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawProfilerDelta(debug_item *it, float xpos, float ypos) {
|
||||
float dt = (float)profiler_delta(it->val);
|
||||
return DrawFormattedText(xpos, ypos, TextFormat("%s: %.02f ms", profiler_name(it->val), dt * 1000.0f));
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawReplaySamples(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
size_t cnt = 0;
|
||||
|
@ -105,7 +88,7 @@ DrawReplaySamples(debug_item *it, float xpos, float ypos) {
|
|||
return DrawFormattedText(xpos, ypos, TextFormat("%d of %d", record_pos, cnt));
|
||||
}
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawReplayFileName(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
return DrawFormattedText(xpos, ypos, TextFormat("%s", replay_filename[0] ? replay_filename : "<unnamed>"));
|
||||
|
@ -113,46 +96,41 @@ DrawReplayFileName(debug_item *it, float xpos, float ypos) {
|
|||
|
||||
// NOTE(zaklaus): demo npcs
|
||||
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawDemoNPCCount(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
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
|
||||
// NOTE(zaklaus): world simulation
|
||||
static inline debug_draw_result
|
||||
DrawWorldStepSize(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
return DrawFormattedText(xpos, ypos, TextFormat("%d ms", (int16_t)(sim_step_size*1000.f)));
|
||||
}
|
||||
|
||||
// NOTE(zaklaus): network stats
|
||||
static inline debug_draw_result
|
||||
static inline debug_draw_result
|
||||
DrawNetworkStats(debug_item *it, float xpos, float ypos) {
|
||||
(void)it;
|
||||
|
||||
|
||||
network_client_stats s = network_client_fetch_stats();
|
||||
|
||||
|
||||
#define _kb(x) ((x) / 1024)
|
||||
|
||||
|
||||
debug_draw_result r;
|
||||
r = DrawFormattedText(xpos, ypos, TextFormat("recv total: %lld kb", _kb(s.total_received)));
|
||||
r = DrawFormattedText(xpos, r.y, TextFormat("sent total: %lld kb", _kb(s.total_sent)));
|
||||
|
||||
|
||||
r = DrawFormattedText(xpos, r.y, TextFormat("dn rate: %.02f kb/sec (%.02f kbit/sec)", _kb(s.incoming_bandwidth), _kb(s.incoming_bandwidth * 8.0f)));
|
||||
r = DrawFormattedText(xpos, r.y, TextFormat("up rate: %.02f kb/sec (%.02f kbit/sec)", _kb(s.outgoing_bandwidth), _kb(s.outgoing_bandwidth * 8.0f)));
|
||||
|
||||
|
||||
r = DrawFormattedText(xpos, r.y, TextFormat("packets sent: %lld", s.packets_sent));
|
||||
r = DrawFormattedText(xpos, r.y, TextFormat("packets lost: %d (%.02f%%)", s.packets_lost, s.packet_loss));
|
||||
|
||||
|
||||
r = DrawFormattedText(xpos, r.y, TextFormat("ping: %d ms", s.ping));
|
||||
|
||||
|
||||
#undef _kb
|
||||
return r;
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
// debug tools written with Nuklear UI
|
||||
#include "models/assets.h"
|
||||
#include "world/blocks.h"
|
||||
#include "models/items.h"
|
||||
|
||||
extern void tooltip_show_cursor(const char* name);
|
||||
extern const char *tooltip_find_desc_contents(const char *name);
|
||||
|
||||
void ToolAssetInspector(void) {
|
||||
if (nk_begin(dev_ui, "Asset Inspector", nk_rect(400, 100, 240, 800),
|
||||
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_TITLE))
|
||||
{
|
||||
for (int i = 0; i < MAX_ASSETS; i++) {
|
||||
uint16_t idx = assets_find(i);
|
||||
if (idx != ASSET_INVALID && nk_tree_push_id(dev_ui, NK_TREE_TAB, asset_names[i], NK_MINIMIZED, i)) {
|
||||
{
|
||||
// draw kind
|
||||
const char *asset_kind_name = assets_get_kind_name(idx);
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "kind: %s", asset_kind_name);
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "spawnable entity: %s", entity_spawn_provided(i) ? "true" : "false");
|
||||
|
||||
if (nk_button_label(dev_ui, "show tooltip")) {
|
||||
tooltip_show_cursor(asset_names[i]);
|
||||
}
|
||||
|
||||
if (nk_button_label(dev_ui, "spawn at me")) {
|
||||
uint64_t e = entity_spawn_id(i);
|
||||
ecs_entity_t plr = camera_get().ent_id;
|
||||
|
||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||
entity_set_position(e, origin->x, origin->y);
|
||||
}
|
||||
|
||||
// draw help text
|
||||
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "description", NK_MINIMIZED, i)) {
|
||||
{
|
||||
const char *desc = tooltip_find_desc_contents(asset_names[i]);
|
||||
if (desc) {
|
||||
nk_layout_row_dynamic(dev_ui, 0, 1);
|
||||
nk_label_wrap(dev_ui, desc);
|
||||
}
|
||||
}
|
||||
nk_tree_pop(dev_ui);
|
||||
}
|
||||
// draw block
|
||||
block_id blk_id = blocks_find(i);
|
||||
if (blk_id != 0xF) {
|
||||
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "block", NK_MINIMIZED, i)) {
|
||||
{
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "symbol: %s", zpl_bprintf("%c", blocks_get_symbol(blk_id)));
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "flags: %u", blocks_get_flags(blk_id));
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "drag: %f", blocks_get_drag(blk_id));
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "friction: %f", blocks_get_friction(blk_id));
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "bounce: %f", blocks_get_bounce(blk_id));
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "velx: %f", blocks_get_velx(blk_id));
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "vely: %f", blocks_get_vely(blk_id));
|
||||
}
|
||||
nk_tree_pop(dev_ui);
|
||||
}
|
||||
}
|
||||
|
||||
// draw item
|
||||
item_id it_id = item_find_no_proxy(i);
|
||||
if (it_id != ASSET_INVALID) {
|
||||
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, "item", NK_MINIMIZED, i)) {
|
||||
{
|
||||
item_desc it = item_get_desc(it_id);
|
||||
|
||||
if (nk_button_label(dev_ui, "spawn")) {
|
||||
ecs_entity_t e = item_spawn(i, it.max_quantity);
|
||||
ecs_entity_t plr = camera_get().ent_id;
|
||||
|
||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||
entity_set_position(e, origin->x, origin->y);
|
||||
}
|
||||
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "usage: %d", it.usage);
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "attachment: %d", it.attachment);
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "max quantity: %d", it.max_quantity);
|
||||
nk_labelf(dev_ui, NK_TEXT_LEFT, "has storage: %s", it.has_storage ? "true" : "false");
|
||||
|
||||
// todo: draw item-specific data
|
||||
}
|
||||
nk_tree_pop(dev_ui);
|
||||
}
|
||||
}
|
||||
}
|
||||
nk_tree_pop(dev_ui);
|
||||
}
|
||||
}
|
||||
nk_end(dev_ui);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ToolEntityInspector(void) {
|
||||
if (nk_begin(dev_ui, "Entity Inspector", nk_rect(660, 100, 240, 800),
|
||||
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_TITLE))
|
||||
{
|
||||
static ecs_query_t *q = 0;
|
||||
if (!q) {
|
||||
q = ecs_query(world_ecs(), {
|
||||
.filter.terms = {
|
||||
{ .id = ecs_id(Position) },
|
||||
{ .id = ecs_id(Classify), .inout = EcsIn }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ecs_iter_t it = ecs_query_iter(world_ecs(), q);
|
||||
while (ecs_query_next(&it)) {
|
||||
Position *p = ecs_field(&it, Position, 1);
|
||||
const Classify *c = ecs_field(&it, Classify, 2);
|
||||
|
||||
for (int i = 0; i < it.count; i++) {
|
||||
if (nk_tree_push_id(dev_ui, NK_TREE_NODE, zpl_bprintf("%lld [%s]", it.entities[i], class_names[c[i].id]), NK_MINIMIZED, (int)it.entities[i])) {
|
||||
{
|
||||
nk_label(dev_ui, "position:", NK_TEXT_LEFT);
|
||||
nk_property_float(dev_ui, "#x:", ZPL_F32_MIN, &p[i].x, ZPL_F32_MAX, 0.1f, 0.2f);
|
||||
nk_property_float(dev_ui, "#y:", ZPL_F32_MIN, &p[i].y, ZPL_F32_MAX, 0.1f, 0.2f);
|
||||
|
||||
if (nk_button_label(dev_ui, "teleport to")) {
|
||||
ecs_entity_t plr = camera_get().ent_id;
|
||||
|
||||
Position const* origin = ecs_get(world_ecs(), it.entities[i], Position);
|
||||
entity_set_position(plr, origin->x, origin->y);
|
||||
}
|
||||
|
||||
if (nk_button_label(dev_ui, "teleport here")) {
|
||||
ecs_entity_t plr = camera_get().ent_id;
|
||||
|
||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||
entity_set_position(it.entities[i], origin->x, origin->y);
|
||||
}
|
||||
}
|
||||
nk_tree_pop(dev_ui);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nk_end(dev_ui);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#include "ecs/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(ItemDrop);
|
||||
ECS_COMPONENT_DECLARE(Inventory);
|
||||
ECS_COMPONENT_DECLARE(ItemContainer);
|
||||
ECS_COMPONENT_DECLARE(Device);
|
||||
ECS_COMPONENT_DECLARE(DemoNPC);
|
||||
ECS_COMPONENT_DECLARE(StreamInfo);
|
||||
|
||||
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, ItemDrop);
|
||||
ECS_COMPONENT_DEFINE(ecs, Inventory);
|
||||
ECS_COMPONENT_DEFINE(ecs, ItemContainer);
|
||||
ECS_COMPONENT_DEFINE(ecs, Device);
|
||||
ECS_COMPONENT_DEFINE(ecs, DemoNPC);
|
||||
ECS_COMPONENT_DEFINE(ecs, StreamInfo);
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
#pragma once
|
||||
#include "flecs/flecs.h"
|
||||
|
||||
#ifndef ecs_get_mut_if
|
||||
#define ecs_get_mut_if(world, entity, component)\
|
||||
(ecs_get(world, entity, component) ? ecs_get_mut(world, entity, component) : NULL)
|
||||
#endif
|
||||
|
||||
#define ITEMS_INVENTORY_SIZE 9
|
||||
#define ITEMS_CONTAINER_SIZE 16
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
} Vector2D;
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint8_t is_dirty;
|
||||
} Chunk;
|
||||
|
||||
typedef struct {
|
||||
uint16_t id;
|
||||
} Drawable;
|
||||
|
||||
typedef Vector2D Position;
|
||||
typedef Vector2D Velocity;
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float mx;
|
||||
float my;
|
||||
float bx;
|
||||
float by;
|
||||
uint8_t use;
|
||||
uint8_t sprint;
|
||||
uint8_t ctrl;
|
||||
uint8_t pick;
|
||||
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;
|
||||
uint8_t selected_item;
|
||||
uint8_t storage_selected_item;
|
||||
uint8_t drop;
|
||||
uint8_t swap;
|
||||
uint8_t swap_storage;
|
||||
uint8_t swap_from;
|
||||
uint8_t swap_to;
|
||||
|
||||
// NOTE(zaklaus): build mode
|
||||
uint8_t num_placements;
|
||||
float placements_x[20];
|
||||
float placements_y[20];
|
||||
uint8_t deletion_mode;
|
||||
} Input;
|
||||
|
||||
typedef struct {
|
||||
uintptr_t peer;
|
||||
uint16_t view_id;
|
||||
uint8_t active;
|
||||
} ClientInfo;
|
||||
|
||||
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;
|
||||
} Health;
|
||||
|
||||
typedef struct {
|
||||
uint16_t id;
|
||||
} Classify;
|
||||
|
||||
typedef struct {
|
||||
uint64_t seats[4];
|
||||
|
||||
float force;
|
||||
float heading;
|
||||
float steer;
|
||||
float wheel_base;
|
||||
|
||||
float speed;
|
||||
float reverse_speed;
|
||||
} Vehicle;
|
||||
|
||||
typedef struct {
|
||||
ecs_entity_t veh;
|
||||
} IsInVehicle;
|
||||
|
||||
typedef struct {
|
||||
uint16_t kind;
|
||||
uint32_t quantity;
|
||||
float merger_time;
|
||||
} ItemDrop;
|
||||
|
||||
typedef struct {
|
||||
ItemDrop items[ITEMS_CONTAINER_SIZE];
|
||||
float pickup_time;
|
||||
} Inventory;
|
||||
|
||||
typedef struct {
|
||||
ItemDrop items[ITEMS_CONTAINER_SIZE];
|
||||
} ItemContainer;
|
||||
|
||||
typedef struct {
|
||||
uint16_t asset;
|
||||
} Device;
|
||||
|
||||
typedef struct {
|
||||
double last_update;
|
||||
double tick_delay;
|
||||
} StreamInfo;
|
||||
|
||||
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(ItemDrop);
|
||||
extern ECS_COMPONENT_DECLARE(Inventory);
|
||||
extern ECS_COMPONENT_DECLARE(ItemContainer);
|
||||
extern ECS_COMPONENT_DECLARE(Device);
|
||||
extern ECS_COMPONENT_DECLARE(DemoNPC);
|
||||
extern ECS_COMPONENT_DECLARE(StreamInfo);
|
||||
|
||||
void ComponentsImport(ecs_world_t *ecs);
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#define DEMO_NPC_MOVE_SPEED 500
|
||||
#define DEMO_NPC_STEER_SPEED 300
|
||||
|
||||
#include <math.h>
|
||||
|
||||
void DemoNPCMoveAround(ecs_iter_t *it) {
|
||||
Velocity *v = ecs_field(it, Velocity, 1);
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
float d = zpl_quake_rsqrt(v[i].x*v[i].x + v[i].y*v[i].y);
|
||||
v[i].x += (v[i].x*d*DEMO_NPC_MOVE_SPEED*safe_dt(it) + zpl_cos(zpl_to_radians((float)(rand()%360)))*DEMO_NPC_STEER_SPEED*safe_dt(it));
|
||||
v[i].y += (v[i].y*d*DEMO_NPC_MOVE_SPEED*safe_dt(it) + zpl_sin(zpl_to_radians((float)(rand()%360)))*DEMO_NPC_STEER_SPEED*safe_dt(it));
|
||||
|
||||
entity_wake(it->entities[i]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
#include "ents/items.h"
|
||||
|
||||
#define ITEM_PICK_RADIUS 25.0f
|
||||
#define ITEM_MERGER_RADIUS 75.0f
|
||||
#define ITEM_ATTRACT_RADIUS 75.0f
|
||||
#define ITEM_ATTRACT_FORCE .98f
|
||||
|
||||
#define ITEM_CONTAINER_REACH_RADIUS 105.0f
|
||||
|
||||
void PickItem(ecs_iter_t *it) {
|
||||
Position *p = ecs_field(it, Position, 2);
|
||||
Inventory *inv = ecs_field(it, Inventory, 3);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (inv[i].pickup_time > game_time()) continue;
|
||||
size_t ents_count;
|
||||
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
||||
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
ItemDrop *drop = 0;
|
||||
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||
Position *p2 = ecs_get_mut(it->world, ents[j], Position);
|
||||
Velocity *v2 = ecs_get_mut(it->world, ents[j], Velocity);
|
||||
|
||||
float dx = p2->x - p[i].x;
|
||||
float dy = p2->y - p[i].y;
|
||||
float range = zpl_sqrt(dx*dx + dy*dy);
|
||||
if (range <= ITEM_PICK_RADIUS) {
|
||||
uint16_t drop_id = item_find(drop->kind);
|
||||
for (size_t k = 0; k < ITEMS_INVENTORY_SIZE; k += 1) {
|
||||
ItemDrop *item = &inv[i].items[k];
|
||||
uint16_t item_id = item_find(item->kind);
|
||||
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)) {
|
||||
uint32_t picked_count = zpl_max(0, drop->quantity);
|
||||
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
|
||||
item->quantity += picked_count;
|
||||
drop->quantity -= picked_count;
|
||||
item->kind = drop->kind;
|
||||
entity_wake(ents[j]);
|
||||
|
||||
if (drop->quantity == 0)
|
||||
item_despawn(ents[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (range <= ITEM_ATTRACT_RADIUS) {
|
||||
v2->x = (p[i].x - p2->x) * ITEM_ATTRACT_FORCE;
|
||||
v2->y = (p[i].y - p2->y) * ITEM_ATTRACT_FORCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ITEM_DROP_PICKUP_TIME 2.5f
|
||||
#define ITEM_DROP_MERGER_TIME 6.5f
|
||||
|
||||
void DropItem(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
Position *p = ecs_field(it, Position, 2);
|
||||
Inventory *inv = ecs_field(it, Inventory, 3);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (!in[i].drop) continue;
|
||||
|
||||
ItemDrop *items = inv[i].items;
|
||||
|
||||
if (in[i].storage_action){
|
||||
if (world_entity_valid(in[i].storage_ent)){
|
||||
ItemContainer *ic = 0;
|
||||
if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){
|
||||
items = ic->items;
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ItemDrop *item = &items[in[i].storage_action ? in[i].storage_selected_item : in[i].selected_item];
|
||||
|
||||
if (item->quantity <= 0)
|
||||
continue;
|
||||
|
||||
uint32_t dropped_count = item->quantity;
|
||||
if (in[i].sprint) {
|
||||
dropped_count /= 2;
|
||||
} else if (in[i].ctrl) {
|
||||
dropped_count = dropped_count > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
if (dropped_count == 0)
|
||||
continue;
|
||||
|
||||
ecs_entity_t te = item_spawn(item->kind, dropped_count);
|
||||
item->quantity -= dropped_count;
|
||||
|
||||
ItemDrop *d = ecs_get_mut(world_ecs(), te, ItemDrop);
|
||||
*d = (ItemDrop){
|
||||
.kind = item->kind,
|
||||
.quantity = dropped_count,
|
||||
.merger_time = game_time() + ITEM_DROP_MERGER_TIME,
|
||||
};
|
||||
|
||||
Position *ipos = ecs_get_mut(it->world, te, Position);
|
||||
*ipos = p[i];
|
||||
|
||||
Velocity *v = ecs_get_mut(it->world, te, Velocity);
|
||||
v->x = in[i].mx * 800.0f;
|
||||
v->y = in[i].my * 800.0f;
|
||||
|
||||
inv[i].pickup_time = game_time() + ITEM_DROP_PICKUP_TIME;
|
||||
in[i].drop = false;
|
||||
|
||||
if (item->quantity == 0) {
|
||||
item->kind = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MergeItems(ecs_iter_t *it) {
|
||||
Position *p = ecs_field(it, Position, 1);
|
||||
ItemDrop *id = ecs_field(it, ItemDrop, 2);
|
||||
|
||||
for (int i = 0; i < it->count; i += 1) {
|
||||
ItemDrop *item = &id[i];
|
||||
|
||||
if (item->merger_time < game_time())
|
||||
continue;
|
||||
|
||||
size_t ents_count;
|
||||
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 1);
|
||||
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
ItemDrop *drop = 0;
|
||||
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||
if (drop->kind != item->kind || (ecs_entity_t)ents[j] == it->entities[i] || drop->quantity == 0 || item->quantity == 0)
|
||||
continue;
|
||||
|
||||
Position const* p2 = ecs_get(it->world, ents[j], Position);
|
||||
|
||||
float dx = p2->x - (p[i].x);
|
||||
float dy = p2->y - (p[i].y);
|
||||
float range = zpl_sqrt(dx*dx + dy*dy);
|
||||
if (range <= ITEM_MERGER_RADIUS) {
|
||||
drop->quantity += item->quantity;
|
||||
item_despawn(it->entities[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwapItems(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
Inventory *inv = ecs_field(it, Inventory, 2);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (!in[i].swap) continue;
|
||||
|
||||
ItemDrop *items = inv[i].items;
|
||||
|
||||
if (in[i].storage_action){
|
||||
if (world_entity_valid(in[i].storage_ent)){
|
||||
ItemContainer *ic = 0;
|
||||
if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){
|
||||
items = ic->items;
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ItemDrop *to = 0;
|
||||
ItemDrop *from = 0;
|
||||
|
||||
if (in[i].swap_storage){
|
||||
in[i].swap_storage = false;
|
||||
|
||||
if (in[i].storage_action){
|
||||
from = &inv[i].items[in[i].swap_from];
|
||||
to = &items[in[i].swap_to];
|
||||
}else{
|
||||
if (world_entity_valid(in[i].storage_ent)){
|
||||
ItemContainer *ic = 0;
|
||||
if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){
|
||||
from = &ic->items[in[i].swap_from];
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
to = &items[in[i].swap_to];
|
||||
}
|
||||
}else{
|
||||
from = &items[in[i].swap_from];
|
||||
to = &items[in[i].swap_to];
|
||||
}
|
||||
|
||||
ZPL_ASSERT(from && to);
|
||||
|
||||
uint16_t to_id = item_find(to->kind);
|
||||
|
||||
if (to == from) {
|
||||
// NOTE(zaklaus): do nothing
|
||||
} else if (to->kind == from->kind && to->quantity > 0) {
|
||||
uint32_t swapped_count = from->quantity;
|
||||
if (in[i].sprint) {
|
||||
swapped_count /= 2;
|
||||
} else if (in[i].ctrl) {
|
||||
swapped_count = 1;
|
||||
}
|
||||
swapped_count = zpl_clamp(swapped_count, 0, item_max_quantity(to_id) - to->quantity);
|
||||
to->quantity += swapped_count;
|
||||
from->quantity -= swapped_count;
|
||||
|
||||
if (swapped_count == 0) {
|
||||
ItemDrop tmp = *to;
|
||||
*to = *from;
|
||||
*from = tmp;
|
||||
}
|
||||
} else if ((in[i].ctrl || in[i].sprint) && to->quantity == 0 && from->quantity > 0) {
|
||||
// NOTE(zaklaus): item split
|
||||
uint32_t split_count = from->quantity / 2;
|
||||
if (in[i].ctrl) {
|
||||
split_count = 1;
|
||||
}
|
||||
to->quantity = split_count;
|
||||
from->quantity -= split_count;
|
||||
to->kind = from->kind;
|
||||
} else {
|
||||
ItemDrop tmp = *to;
|
||||
*to = *from;
|
||||
*from = tmp;
|
||||
}
|
||||
|
||||
in[i].swap = false;
|
||||
}
|
||||
}
|
||||
|
||||
void UseItem(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
Position *p = ecs_field(it, Position, 2);
|
||||
Inventory *inv = ecs_field(it, Inventory, 3);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (!in[i].use && !in[i].num_placements) continue;
|
||||
|
||||
if (in[i].storage_action){
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemDrop *item = &inv[i].items[in[i].selected_item];
|
||||
uint16_t item_id = 0;
|
||||
item_usage usage = UKIND_DELETE;
|
||||
|
||||
if (!in[i].deletion_mode){
|
||||
item_id = item_find(item->kind);
|
||||
usage = item_get_usage(item_id);
|
||||
if (!item || item->quantity <= 0) continue;
|
||||
}
|
||||
|
||||
if (!in[i].use && usage == UKIND_DELETE){
|
||||
for (size_t j = 0; j < in[i].num_placements; j++) {
|
||||
world_chunk_destroy_block(in[i].placements_x[j], in[i].placements_y[j], true);
|
||||
}
|
||||
}
|
||||
else if (in[i].use && usage > UKIND_END_PLACE)
|
||||
item_use(it->world, item, p[i], 0);
|
||||
else if (in[i].num_placements > 0 && usage < UKIND_END_PLACE) {
|
||||
asset_id ofs = 0;
|
||||
if (item_get_place_directional(item_id) && in[i].num_placements >= 2) {
|
||||
float p1x = in[i].placements_x[0];
|
||||
float p1y = in[i].placements_y[0];
|
||||
float p2x = in[i].placements_x[1];
|
||||
float p2y = in[i].placements_y[1];
|
||||
float sx = zpl_sign0(p2x-p1x);
|
||||
float sy = zpl_sign0(p2y-p1y);
|
||||
ofs = (sx < 0.0f) ? 1 : 2;
|
||||
if (sx == 0.0f) {
|
||||
ofs = (sy < 0.0f) ? 3 : 4;
|
||||
}
|
||||
} else if(item_get_place_directional(item_id)) {
|
||||
// NOTE(zaklaus): ensure we pick the first variant
|
||||
ofs = 1;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < in[i].num_placements; j++) {
|
||||
Position pos = {.x = in[i].placements_x[j], .y = in[i].placements_y[j]};
|
||||
item_use(it->world, item, pos, ofs);
|
||||
}
|
||||
|
||||
in[i].num_placements = 0;
|
||||
}
|
||||
|
||||
entity_wake(it->entities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectContainers(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
|
||||
for (int i = 0; i < it->count; ++i) {
|
||||
if (!in[i].pick) continue;
|
||||
|
||||
if ((in[i].sel_ent && ecs_get(it->world, in[i].sel_ent, ItemContainer)) || !in[i].sel_ent)
|
||||
in[i].storage_ent = in[i].sel_ent;
|
||||
}
|
||||
}
|
||||
|
||||
void HarvestIntoContainers(ecs_iter_t *it) {
|
||||
ItemContainer *in = ecs_field(it, ItemContainer, 1);
|
||||
Position *p = ecs_field(it, Position, 2);
|
||||
|
||||
for (int i = 0; i < it->count; ++i) {
|
||||
// NOTE(zaklaus): find any item
|
||||
size_t ents_count;
|
||||
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 0);
|
||||
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
ItemDrop *drop = 0;
|
||||
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||
const Position *p2 = ecs_get(it->world, ents[j], Position);
|
||||
|
||||
float dx = p2->x - p[i].x;
|
||||
float dy = p2->y - p[i].y;
|
||||
float range = zpl_sqrt(dx*dx + dy*dy);
|
||||
if (range <= ITEM_PICK_RADIUS) {
|
||||
uint16_t drop_id = item_find(drop->kind);
|
||||
for (size_t k = 0; k < ITEMS_CONTAINER_SIZE; k += 1) {
|
||||
ItemDrop *item = &in->items[k];
|
||||
uint16_t item_id = item_find(item->kind);
|
||||
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)) {
|
||||
uint32_t picked_count = zpl_max(0, drop->quantity);
|
||||
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
|
||||
item->quantity += picked_count;
|
||||
drop->quantity -= picked_count;
|
||||
item->kind = drop->kind;
|
||||
entity_wake(ents[j]);
|
||||
entity_wake(it->entities[i]);
|
||||
|
||||
if (drop->quantity == 0)
|
||||
item_despawn(ents[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
#include "models/entity.h"
|
||||
#include "ents/entity.h"
|
||||
|
||||
#define PLR_MOVE_SPEED 800.0f
|
||||
#define PLR_MOVE_SPEED_MULT 1.5f
|
||||
|
||||
void MovementImpulse(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
|
@ -8,7 +11,7 @@ void MovementImpulse(ecs_iter_t *it) {
|
|||
for (int i = 0; i < it->count; i++) {
|
||||
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y);
|
||||
float drag = zpl_clamp(blocks_get_drag(lookup.bid), 0.0f, 1.0f);
|
||||
float speed = game_rules.plr_move_speed * (in[i].sprint ? game_rules.plr_move_speed_mult : 1.0f);
|
||||
float speed = PLR_MOVE_SPEED * (in[i].sprint ? PLR_MOVE_SPEED_MULT : 1.0f);
|
||||
v[i].x += in[i].x*speed*drag*safe_dt(it);
|
||||
v[i].y -= in[i].y*speed*drag*safe_dt(it);
|
||||
|
|
@ -1,14 +1,16 @@
|
|||
#include "dev/debug_draw.h"
|
||||
#include "models/entity.h"
|
||||
#include "debug/debug_draw.h"
|
||||
#include "ents/entity.h"
|
||||
|
||||
#define VEH_ENTER_RADIUS 45.0f
|
||||
|
||||
void LeaveVehicle(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
IsInVehicle *vehp = ecs_field(it, IsInVehicle, 2);
|
||||
Velocity *v = ecs_field(it, Velocity, 3);
|
||||
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (!in[i].use) continue;
|
||||
|
||||
|
||||
Vehicle *veh = 0;
|
||||
if ((veh = ecs_get_mut_if(it->world, vehp->veh, Vehicle))) {
|
||||
for (int k = 0; k < 4; k++) {
|
||||
|
@ -17,16 +19,16 @@ void LeaveVehicle(ecs_iter_t *it) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
in[i].use = false;
|
||||
ecs_remove(it->world, it->entities[i], IsInVehicle);
|
||||
|
||||
|
||||
// NOTE(zaklaus): push passenger out
|
||||
{
|
||||
float px = zpl_cos(veh->heading)*400.0f;
|
||||
float py = zpl_sin(veh->heading)*400.0f;
|
||||
v[i].x += py;
|
||||
v[i].y -= px;
|
||||
v->x += py;
|
||||
v->y -= px;
|
||||
}
|
||||
} else {
|
||||
ZPL_PANIC("unreachable code");
|
||||
|
@ -37,31 +39,29 @@ void LeaveVehicle(ecs_iter_t *it) {
|
|||
void EnterVehicle(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
Position *p = ecs_field(it, Position, 2);
|
||||
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (!in[i].use) continue;
|
||||
|
||||
|
||||
size_t ents_count;
|
||||
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
||||
bool has_entered_veh = false;
|
||||
|
||||
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
Vehicle *veh = 0;
|
||||
|
||||
|
||||
if (has_entered_veh) break;
|
||||
|
||||
veh = ecs_get_mut_if(it->world, ents[j], Vehicle);
|
||||
|
||||
|
||||
if ((veh = ecs_get_mut_if(it->world, ents[j], Vehicle))) {
|
||||
Position const* p2 = ecs_get(it->world, ents[j], Position);
|
||||
|
||||
|
||||
float dx = p2->x - p[i].x;
|
||||
float dy = p2->y - p[i].y;
|
||||
float range = zpl_sqrt(dx*dx + dy*dy);
|
||||
if (range <= game_rules.veh_enter_radius) {
|
||||
if (range <= VEH_ENTER_RADIUS) {
|
||||
for (int k = 0; k < 4; k++) {
|
||||
if (veh->seats[k] != 0) continue;
|
||||
|
||||
|
||||
// NOTE(zaklaus): We can enter the vehicle, yay!
|
||||
veh->seats[k] = it->entities[i];
|
||||
ecs_set(it->world, it->entities[i], IsInVehicle, {
|
||||
|
@ -78,70 +78,71 @@ void EnterVehicle(ecs_iter_t *it) {
|
|||
}
|
||||
}
|
||||
|
||||
#define VEHICLE_FORCE 240.8f
|
||||
#define VEHICLE_ACCEL 0.032f
|
||||
#define VEHICLE_DECEL 0.28f
|
||||
#define VEHICLE_STEER 35.89f
|
||||
#define VEHICLE_STEER_COMPENSATION 4.0f
|
||||
#define VEHICLE_STEER_REVERT 6.0941816f
|
||||
#define VEHICLE_POWER 97.89f
|
||||
#define VEHICLE_BRAKE_FORCE 0.84f
|
||||
|
||||
void VehicleHandling(ecs_iter_t *it) {
|
||||
Vehicle *veh = ecs_field(it, Vehicle, 1);
|
||||
Position *p = ecs_field(it, Position, 2);
|
||||
Velocity *v = ecs_field(it, Velocity, 3);
|
||||
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
Vehicle *car = &veh[i];
|
||||
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
// NOTE(zaklaus): Perform seat cleanup
|
||||
if (!world_entity_valid(veh[i].seats[j])) {
|
||||
veh[i].seats[j] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
ecs_entity_t pe = veh[i].seats[j];
|
||||
|
||||
|
||||
// NOTE(zaklaus): Handle driver input
|
||||
if (j == 0) {
|
||||
Input const* in = ecs_get(it->world, pe, Input);
|
||||
|
||||
car->force += zpl_lerp(0.0f, in->y * game_rules.vehicle_force, (zpl_sign(in->y) == zpl_sign(car->force) ? 1.0f : 3.0f) * game_rules.vehicle_accel*safe_dt(it));
|
||||
|
||||
car->force += zpl_lerp(0.0f, in->y * VEHICLE_FORCE, (zpl_sign(in->y) == zpl_sign(car->force) ? 1.0f : 3.0f) * VEHICLE_ACCEL*safe_dt(it));
|
||||
if (in->sprint) {
|
||||
car->force = zpl_lerp(car->force, 0.0f, game_rules.vehicle_brake_force*safe_dt(it));
|
||||
|
||||
car->force = zpl_lerp(car->force, 0.0f, VEHICLE_BRAKE_FORCE*safe_dt(it));
|
||||
|
||||
if (zpl_abs(car->force) < 5.5f)
|
||||
car->force = 0.0f;
|
||||
}
|
||||
float steer_mod = (1 - zpl_abs(car->force) / car->speed) + game_rules.vehicle_steer_compensation * safe_dt(it);
|
||||
car->steer = zpl_lerp(car->steer, 0.0f, safe_dt(it)*game_rules.vehicle_steer_revert);
|
||||
car->steer += (in->x * game_rules.vehicle_steer * steer_mod)*safe_dt(it);
|
||||
float steer_mod = (1 - zpl_abs(car->force) / car->speed) + VEHICLE_STEER_COMPENSATION * safe_dt(it);
|
||||
car->steer = zpl_lerp(car->steer, 0.0f, safe_dt(it)*VEHICLE_STEER_REVERT);
|
||||
car->steer += (in->x * VEHICLE_STEER * steer_mod)*safe_dt(it);
|
||||
car->steer = zpl_clamp(car->steer, -60.0f, 60.0f);
|
||||
|
||||
// if (in->x != 0) {
|
||||
// // Add a sideways velocity to the car. This will make the car move sideways,
|
||||
// // giving the appearance of a drift. The actual amount of sideways velocity
|
||||
// // will need to be fine-tuned.
|
||||
// v[i].x += in->x * steer_mod * -zpl_sin(car->heading) * car->force;
|
||||
// v[i].y += in->x * steer_mod * zpl_cos(car->heading) * car->force;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
car->force = zpl_clamp(car->force, car->reverse_speed, car->speed);
|
||||
|
||||
|
||||
// NOTE(zaklaus): Vehicle physics
|
||||
float fr_x = p[i].x + (car->wheel_base/2.0f) * zpl_cos(car->heading);
|
||||
float fr_y = p[i].y + (car->wheel_base/2.0f) * zpl_sin(car->heading);
|
||||
|
||||
|
||||
float bk_x = p[i].x - (car->wheel_base/2.0f) * zpl_cos(car->heading);
|
||||
float bk_y = p[i].y - (car->wheel_base/2.0f) * zpl_sin(car->heading);
|
||||
|
||||
|
||||
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y);
|
||||
float drag = zpl_clamp(blocks_get_drag(lookup.bid), 0.0f, 1.0f);
|
||||
|
||||
bk_x += car->force * drag * zpl_cos(car->heading) * safe_dt(it)*game_rules.vehicle_power;
|
||||
bk_y += car->force * drag * zpl_sin(car->heading) * safe_dt(it)*game_rules.vehicle_power;
|
||||
fr_x += car->force * drag * zpl_cos(car->heading + zpl_to_radians(car->steer)) * safe_dt(it)*game_rules.vehicle_power;
|
||||
fr_y += car->force * drag * zpl_sin(car->heading + zpl_to_radians(car->steer)) * safe_dt(it)*game_rules.vehicle_power;
|
||||
|
||||
|
||||
bk_x += car->force * drag * zpl_cos(car->heading) * safe_dt(it)*VEHICLE_POWER;
|
||||
bk_y += car->force * drag * zpl_sin(car->heading) * safe_dt(it)*VEHICLE_POWER;
|
||||
fr_x += car->force * drag * zpl_cos(car->heading + zpl_to_radians(car->steer)) * safe_dt(it)*VEHICLE_POWER;
|
||||
fr_y += car->force * drag * zpl_sin(car->heading + zpl_to_radians(car->steer)) * safe_dt(it)*VEHICLE_POWER;
|
||||
|
||||
v[i].x += ((fr_x + bk_x) / 2.0f - p[i].x);
|
||||
v[i].y += ((fr_y + bk_y) / 2.0f - p[i].y);
|
||||
car->heading = zpl_arctan2(fr_y - bk_y, fr_x - bk_x);
|
||||
|
||||
|
||||
float check_x = p[i].x+PHY_LOOKAHEAD(v[i].x);
|
||||
float check_y = p[i].y+PHY_LOOKAHEAD(v[i].y);
|
||||
world_block_lookup lookahead = world_block_from_realpos(check_x, check_y);
|
||||
|
@ -154,11 +155,11 @@ void VehicleHandling(ecs_iter_t *it) {
|
|||
car->force = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (!world_entity_valid(veh[i].seats[j])) continue;
|
||||
ecs_entity_t pe = veh[i].seats[j];
|
||||
|
||||
|
||||
// NOTE(zaklaus): Update passenger position
|
||||
{
|
||||
Velocity *v2 = ecs_get_mut(it->world, pe, Velocity);
|
||||
|
@ -166,22 +167,22 @@ void VehicleHandling(ecs_iter_t *it) {
|
|||
*v2 = v[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (zpl_abs(car->force) > ENTITY_ACTION_VELOCITY_THRESHOLD) {
|
||||
entity_wake(it->entities[i]);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
debug_v2 b2 = {p[i].x + zpl_cos(car->heading)*(car->wheel_base), p[i].y + zpl_sin(car->heading)*(car->wheel_base)};
|
||||
debug_push_line((debug_v2){p[i].x, p[i].y}, b2, 0x0000FFFF);
|
||||
|
||||
|
||||
// NOTE(zaklaus): force
|
||||
{
|
||||
float dx = zpl_cos(car->heading);
|
||||
float dy = zpl_sin(car->heading);
|
||||
debug_push_circle((debug_v2){p[i].x+dx*car->force, p[i].y+dy*car->force}, 5.0f, 0x00FF00FF);
|
||||
}
|
||||
|
||||
|
||||
// NOTE(zaklaus): steer
|
||||
{
|
||||
float dx = zpl_sin(car->heading);
|
||||
|
@ -195,7 +196,7 @@ void VehicleHandling(ecs_iter_t *it) {
|
|||
|
||||
void ClearVehicle(ecs_iter_t *it) {
|
||||
Vehicle *veh = ecs_field(it, Vehicle, 1);
|
||||
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
for (int k = 0; k < 4; k++) {
|
||||
if (world_entity_valid(veh[i].seats[k])) {
|
|
@ -0,0 +1,226 @@
|
|||
#include "zpl.h"
|
||||
#include "ecs/systems.h"
|
||||
#include "ecs/components.h"
|
||||
#include "world/world.h"
|
||||
#include "world/blocks.h"
|
||||
#include "platform/profiler.h"
|
||||
#include "debug/debug_draw.h"
|
||||
#include "core/game.h"
|
||||
|
||||
#define PHY_BLOCK_COLLISION 1
|
||||
#define PHY_WALK_DRAG 4.23f
|
||||
#define PHY_LOOKAHEAD(x) (zpl_sign(x)*16.0f)
|
||||
|
||||
#include "modules/system_onfoot.c"
|
||||
#include "modules/system_demo.c"
|
||||
#include "modules/system_vehicle.c"
|
||||
#include "modules/system_items.c"
|
||||
|
||||
static inline float physics_correction(float x, float vx, float bounce) {
|
||||
float r = (((zpl_max(0.0f, (WORLD_BLOCK_SIZE/2.0f) - zpl_abs(x))*zpl_sign(x)))*(WORLD_BLOCK_SIZE/2.0f));
|
||||
return r + (-vx*bounce);
|
||||
}
|
||||
|
||||
void IntegratePositions(ecs_iter_t *it) {
|
||||
profile(PROF_INTEGRATE_POS) {
|
||||
Position *p = ecs_field(it, Position, 1);
|
||||
Velocity *v = ecs_field(it, Velocity, 2);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (ecs_get(it->world, it->entities[i], IsInVehicle)) {
|
||||
continue;
|
||||
}
|
||||
if (zpl_abs(v[i].x) >= 0.001f || zpl_abs(v[i].y) >= 0.001f) {
|
||||
// NOTE(zaklaus): world bounds
|
||||
{
|
||||
float w = (float)world_dim();
|
||||
p[i].x = zpl_clamp(p[i].x, 0, w-1);
|
||||
p[i].y = zpl_clamp(p[i].y, 0, w-1);
|
||||
}
|
||||
|
||||
#if PHY_BLOCK_COLLISION==1
|
||||
// NOTE(zaklaus): X axis
|
||||
{
|
||||
world_block_lookup lookup = world_block_from_realpos(p[i].x+PHY_LOOKAHEAD(v[i].x), p[i].y);
|
||||
uint32_t flags = blocks_get_flags(lookup.bid);
|
||||
float bounce = blocks_get_bounce(lookup.bid);
|
||||
if (flags & BLOCK_FLAG_COLLISION) {
|
||||
v[i].x = physics_correction(lookup.ox, v[i].x, bounce);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(zaklaus): Y axis
|
||||
{
|
||||
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y+PHY_LOOKAHEAD(v[i].y));
|
||||
uint32_t flags = blocks_get_flags(lookup.bid);
|
||||
float bounce = blocks_get_bounce(lookup.bid);
|
||||
if (flags & BLOCK_FLAG_COLLISION) {
|
||||
v[i].y = physics_correction(lookup.oy, v[i].y, bounce);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
entity_set_position(it->entities[i], p[i].x+v[i].x*safe_dt(it), p[i].y+v[i].y*safe_dt(it));
|
||||
}
|
||||
|
||||
{
|
||||
debug_v2 a = {p[i].x, p[i].y};
|
||||
debug_v2 b = {p[i].x+v[i].x, p[i].y+v[i].y};
|
||||
debug_push_line(a, b, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define HAZARD_BLOCK_TIME 1.0f
|
||||
#define HAZARD_BLOCK_DMG 5.0f
|
||||
|
||||
void HurtOnHazardBlock(ecs_iter_t *it) {
|
||||
Position *p = ecs_field(it, Position, 1);
|
||||
Health *h = ecs_field(it, Health, 2);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (h->pain_time < 0.0f) {
|
||||
h->pain_time = HAZARD_BLOCK_TIME;
|
||||
world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y);
|
||||
if (blocks_get_flags(l.bid) & BLOCK_FLAG_HAZARD) {
|
||||
h->hp -= HAZARD_BLOCK_DMG;
|
||||
h->hp = zpl_max(0.0f, h->hp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define HP_REGEN_TIME 2.0f
|
||||
#define HP_REGEN_PAIN_COOLDOWN 5.0f
|
||||
#define HP_REGEN_RECOVERY 15.0f
|
||||
|
||||
void RegenerateHP(ecs_iter_t *it) {
|
||||
Health *h = ecs_field(it, Health, 1);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (h[i].pain_time < 0.0f) {
|
||||
if (h[i].heal_time < 0.0f && h[i].hp < h[i].max_hp) {
|
||||
h[i].heal_time = HP_REGEN_TIME;
|
||||
h[i].hp += HP_REGEN_RECOVERY;
|
||||
h[i].hp = zpl_min(h[i].max_hp, h[i].hp);
|
||||
entity_wake(it->entities[i]);
|
||||
} else {
|
||||
h[i].heal_time -= safe_dt(it);
|
||||
}
|
||||
} else {
|
||||
h[i].pain_time -= safe_dt(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResetActivators(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
in[i].use = false;
|
||||
in[i].swap = false;
|
||||
in[i].drop = false;
|
||||
in[i].pick = false;
|
||||
in[i].num_placements = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyWorldDragOnVelocity(ecs_iter_t *it) {
|
||||
Position *p = ecs_field(it, Position, 1);
|
||||
Velocity *v = ecs_field(it, Velocity, 2);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
if (zpl_abs(v[i].x) < 0.001f && zpl_abs(v[i].y) < 0.001f) continue;
|
||||
if (ecs_get(it->world, it->entities[i], IsInVehicle)) {
|
||||
continue;
|
||||
}
|
||||
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y);
|
||||
float drag = zpl_clamp(blocks_get_drag(lookup.bid), 0.0f, 1.0f);
|
||||
float friction = blocks_get_friction(lookup.bid);
|
||||
float velx = blocks_get_velx(lookup.bid);
|
||||
float vely = blocks_get_vely(lookup.bid);
|
||||
v[i].x = zpl_lerp(v[i].x, zpl_max(0.0f, zpl_abs(velx))*zpl_sign(velx), PHY_WALK_DRAG*drag*friction*safe_dt(it));
|
||||
v[i].y = zpl_lerp(v[i].y, zpl_max(0.0f, zpl_abs(vely))*zpl_sign(vely), PHY_WALK_DRAG*drag*friction*safe_dt(it));
|
||||
|
||||
if ( zpl_abs(v[i].x) > ENTITY_ACTION_VELOCITY_THRESHOLD
|
||||
|| zpl_abs(v[i].y) > ENTITY_ACTION_VELOCITY_THRESHOLD) {
|
||||
entity_wake(it->entities[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PLAYER_MAX_INTERACT_RANGE 35.0f
|
||||
|
||||
void PlayerClosestInteractable(ecs_iter_t *it){
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
|
||||
for (int i = 0; i < it->count; ++i) {
|
||||
size_t ents_count;
|
||||
int64_t *ents = world_chunk_fetch_entities_realpos(in[i].bx, in[i].by, &ents_count);
|
||||
|
||||
ecs_entity_t closest_pick = 0;
|
||||
float min_pick = ZPL_F32_MAX;
|
||||
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
const Position *p2 = ecs_get(it->world, ents[j], Position);
|
||||
if (!p2) continue;
|
||||
|
||||
float dx = p2->x - in[i].bx;
|
||||
float dy = p2->y - in[i].by;
|
||||
float range = zpl_sqrt(dx*dx + dy*dy);
|
||||
if (range <= PLAYER_MAX_INTERACT_RANGE && range < min_pick) {
|
||||
min_pick = range;
|
||||
closest_pick = ents[j];
|
||||
}
|
||||
}
|
||||
|
||||
in[i].pick_ent = closest_pick;
|
||||
|
||||
if (in[i].pick)
|
||||
in[i].sel_ent = (in[i].sel_ent == closest_pick) ? 0 : closest_pick;
|
||||
}
|
||||
}
|
||||
|
||||
void EnableWorldEdit(ecs_iter_t *it) {
|
||||
world_set_stage(it->world);
|
||||
}
|
||||
|
||||
void DisableWorldEdit(ecs_iter_t *it) {
|
||||
(void)it;
|
||||
world_set_stage(NULL);
|
||||
}
|
||||
|
||||
void SystemsImport(ecs_world_t *ecs) {
|
||||
ECS_MODULE(ecs, Systems);
|
||||
|
||||
ECS_SYSTEM(ecs, EnableWorldEdit, EcsOnLoad);
|
||||
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, components.Input, components.Velocity, components.Position, !components.IsInVehicle);
|
||||
ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, components.Velocity, components.DemoNPC);
|
||||
|
||||
ECS_SYSTEM(ecs, ApplyWorldDragOnVelocity, EcsOnUpdate, components.Position, components.Velocity);
|
||||
ECS_SYSTEM(ecs, HurtOnHazardBlock, EcsOnUpdate, components.Position, components.Health);
|
||||
ECS_SYSTEM(ecs, RegenerateHP, EcsOnUpdate, components.Health);
|
||||
ECS_SYSTEM(ecs, VehicleHandling, EcsOnUpdate, components.Vehicle, components.Position, components.Velocity);
|
||||
|
||||
ECS_SYSTEM(ecs, IntegratePositions, EcsOnValidate, components.Position, components.Velocity);
|
||||
|
||||
ECS_SYSTEM(ecs, EnterVehicle, EcsPostUpdate, components.Input, components.Position, !components.IsInVehicle);
|
||||
ECS_SYSTEM(ecs, LeaveVehicle, EcsPostUpdate, components.Input, components.IsInVehicle, components.Velocity);
|
||||
|
||||
ECS_SYSTEM(ecs, PlayerClosestInteractable, EcsPostUpdate, components.Input);
|
||||
ECS_SYSTEM(ecs, PickItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
|
||||
ECS_SYSTEM(ecs, DropItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
|
||||
ECS_SYSTEM(ecs, SwapItems, EcsPostUpdate, components.Input, components.Inventory);
|
||||
//ECS_SYSTEM(ecs, MergeItems, EcsPostUpdate, components.Position, components.ItemDrop);
|
||||
ECS_SYSTEM(ecs, UseItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
|
||||
ECS_SYSTEM(ecs, InspectContainers, EcsPostUpdate, components.Input, !components.IsInVehicle);
|
||||
ECS_SYSTEM(ecs, HarvestIntoContainers, EcsPostUpdate, components.ItemContainer, components.Position);
|
||||
|
||||
ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input);
|
||||
|
||||
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);
|
||||
|
||||
ECS_SYSTEM(ecs, DisableWorldEdit, EcsPostUpdate);
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
#include "flecs/flecs.h"
|
||||
|
||||
static inline float safe_dt(ecs_iter_t *it) {
|
||||
return zpl_min(it->delta_time, 0.03334f);
|
||||
}
|
||||
|
||||
void SystemsImport(ecs_world_t *ecs);
|
|
@ -1,17 +1,16 @@
|
|||
#include "models/device.h"
|
||||
#include "models/entity.h"
|
||||
#include "ents/device.h"
|
||||
#include "ents/entity.h"
|
||||
#include "world/entity_view.h"
|
||||
#include "world/world.h"
|
||||
|
||||
#include "models/components.h"
|
||||
#include "ecs/components.h"
|
||||
|
||||
uint64_t device_spawn(asset_id id) {
|
||||
uint64_t device_spawn(asset_id id) {
|
||||
ecs_entity_t e = entity_spawn(EKIND_DEVICE);
|
||||
|
||||
|
||||
Device *dev = ecs_get_mut(world_ecs(), e, Device);
|
||||
zpl_zero_item(dev);
|
||||
dev->asset = id;
|
||||
|
||||
|
||||
return (uint64_t)e;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include "platform/system.h"
|
||||
#include "models/assets.h"
|
||||
#include "gen/assets.h"
|
||||
|
||||
uint64_t device_spawn(asset_id id);
|
||||
void device_despawn(uint64_t ent_id);
|
|
@ -1,73 +1,55 @@
|
|||
#include "models/entity.h"
|
||||
#include "ents/entity.h"
|
||||
#include "world/entity_view.h"
|
||||
#include "flecs.h"
|
||||
#include "flecs/flecs.h"
|
||||
#include "librg.h"
|
||||
#include "world/world.h"
|
||||
|
||||
#include "models/components.h"
|
||||
#include "systems/systems.h"
|
||||
#include "ecs/components.h"
|
||||
#include "ecs/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 "models/prefabs/prefabs_list.c"
|
||||
#define MAX_ENTITY_SPAWNDEFS ((size_t)zpl_array_count(entity_spawnlist))
|
||||
#include "entity_spawnlist.c"
|
||||
|
||||
void entity_default_spawnlist(void) {
|
||||
zpl_array_init(entity_spawnlist, zpl_heap());
|
||||
void entity_spawndef_cleanup() {
|
||||
zpl_array_free(entity_spawnlist); entity_spawnlist = NULL;
|
||||
}
|
||||
void entity_spawndef_register(spawndef def) {
|
||||
if (!entity_spawnlist) {
|
||||
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);
|
||||
zpl_array_append(entity_spawnlist, def);
|
||||
}
|
||||
|
||||
uint64_t entity_spawn(uint16_t class_id) {
|
||||
ecs_entity_t e = ecs_new(world_ecs(), 0);
|
||||
|
||||
|
||||
ecs_set(world_ecs(), e, Classify, { .id = 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_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_chunk_set(world_tracker(), e, librg_chunk_from_realpos(world_tracker(), pos->x, pos->y, 0));
|
||||
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
|
||||
librg_entity_owner_set(world_collision_grid(), e, (int64_t)e);
|
||||
}
|
||||
|
||||
|
||||
return (uint64_t)e;
|
||||
}
|
||||
|
||||
uint64_t entity_spawn_id(uint16_t id){
|
||||
for (size_t i = 0; i < MAX_ENTITY_SPAWNDEFS; ++i){
|
||||
for (zpl_isize i = 0; i < zpl_array_count(entity_spawnlist); ++i){
|
||||
if (entity_spawnlist[i].id == id){
|
||||
ZPL_ASSERT(entity_spawnlist[i].proc);
|
||||
return entity_spawnlist[i].proc();
|
||||
|
@ -76,28 +58,8 @@ uint64_t entity_spawn_id(uint16_t id){
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint64_t entity_spawn_id_with_data(uint16_t id, void *udata){
|
||||
for (size_t i = 0; i < MAX_ENTITY_SPAWNDEFS; ++i){
|
||||
if (entity_spawnlist[i].id == id){
|
||||
ZPL_ASSERT(entity_spawnlist[i].proc_udata);
|
||||
return entity_spawnlist[i].proc_udata(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]);
|
||||
}
|
||||
|
@ -105,17 +67,14 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -133,12 +92,12 @@ void entity_update_action_timers() {
|
|||
ecs_streaminfo = ecs_query_new(world_ecs(), "components.StreamInfo");
|
||||
last_update_time = get_cached_time();
|
||||
}
|
||||
|
||||
|
||||
ecs_iter_t it = ecs_query_iter(world_ecs(), ecs_streaminfo);
|
||||
|
||||
|
||||
while (ecs_query_next(&it)) {
|
||||
StreamInfo *si = ecs_field(&it, StreamInfo, 1);
|
||||
|
||||
|
||||
for (int32_t i = 0; i < it.count; i++) {
|
||||
if (si[i].last_update < get_cached_time()) {
|
||||
si[i].last_update = get_cached_time() + si[i].tick_delay;
|
||||
|
@ -146,7 +105,7 @@ void entity_update_action_timers() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
last_update_time = get_cached_time();
|
||||
}
|
||||
|
|
@ -1,21 +1,24 @@
|
|||
#pragma once
|
||||
#include "platform/system.h"
|
||||
#include "gen/assets.h"
|
||||
|
||||
#define ENTITY_ACTION_VELOCITY_THRESHOLD 0.001f
|
||||
#define ENTITY_ACTION_VELOCITY_THRESHOLD 0.05f
|
||||
|
||||
typedef struct {
|
||||
asset_id id;
|
||||
uint64_t (*proc)();
|
||||
} spawndef;
|
||||
|
||||
void entity_spawndef_setup();
|
||||
void entity_spawndef_cleanup();
|
||||
void entity_spawndef_register(spawndef def);
|
||||
|
||||
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);
|
|
@ -0,0 +1,8 @@
|
|||
// NOTE(zaklaus): access to spawners
|
||||
#include "ents/storage.h"
|
||||
|
||||
static spawndef *entity_spawnlist = 0;
|
||||
|
||||
void entity_spawndef_setup(void) {
|
||||
entity_spawndef_register((spawndef){ .id = ASSET_CHEST, .proc = storage_spawn });
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
#include "ents/items.h"
|
||||
#include "ents/entity.h"
|
||||
#include "world/entity_view.h"
|
||||
#include "world/world.h"
|
||||
#include "world/blocks.h"
|
||||
|
||||
#include "ecs/components.h"
|
||||
|
||||
#include "zpl.h"
|
||||
|
||||
#include "items_list.c"
|
||||
|
||||
void item_cleanup() {
|
||||
zpl_array_free(items); items = NULL;
|
||||
}
|
||||
|
||||
void item_register(item_desc desc) {
|
||||
if (!items) {
|
||||
zpl_array_init(items, zpl_heap());
|
||||
}
|
||||
|
||||
zpl_array_append(items, desc);
|
||||
}
|
||||
|
||||
static inline item_id item_resolve_proxy(item_id id) {
|
||||
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
|
||||
item_usage usage = items[id].usage;
|
||||
if (usage == UKIND_PROXY) {
|
||||
return item_find(items[id].proxy.id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline asset_id item_fix_kind(asset_id id) {
|
||||
return items[item_find(id)].kind;
|
||||
}
|
||||
|
||||
uint64_t item_spawn(asset_id kind, uint32_t qty) {
|
||||
ecs_entity_t e = entity_spawn(EKIND_ITEM);
|
||||
|
||||
ItemDrop *d = ecs_get_mut(world_ecs(), e, ItemDrop);
|
||||
*d = (ItemDrop){
|
||||
.kind = item_fix_kind(kind),
|
||||
.quantity = qty,
|
||||
.merger_time = 0,
|
||||
};
|
||||
|
||||
return (uint64_t)e;
|
||||
}
|
||||
|
||||
item_id item_find(asset_id kind) {
|
||||
for (item_id i=0; i<zpl_array_count(items); i++) {
|
||||
if (items[i].kind == kind)
|
||||
return item_resolve_proxy(i);
|
||||
}
|
||||
return ASSET_INVALID;
|
||||
}
|
||||
|
||||
void item_use(ecs_world_t *ecs, ItemDrop *it, Position p, uint64_t udata) {
|
||||
(void)ecs;
|
||||
uint16_t it_id = item_find(it->kind);
|
||||
item_desc *desc = &items[it_id];
|
||||
if (it->quantity <= 0) return;
|
||||
switch (item_get_usage(it_id)) {
|
||||
case UKIND_HOLD: /* NOOP */ break;
|
||||
case UKIND_PLACE:{
|
||||
world_block_lookup l = world_block_from_realpos(p.x, p.y);
|
||||
if (l.is_outer && l.bid > 0) {
|
||||
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++;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// NOTE(zaklaus): This is an inner layer block, we can't build over it if it has a collision!
|
||||
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
// NOTE(zaklaus): This is an inner layer block, we can't build over it if it has a collision!
|
||||
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_DELETE:
|
||||
case UKIND_END_PLACE:
|
||||
case UKIND_PROXY:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void item_despawn(uint64_t id) {
|
||||
entity_despawn(id);
|
||||
}
|
||||
|
||||
uint32_t item_max_quantity(item_id id) {
|
||||
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
|
||||
return items[id].max_quantity;
|
||||
}
|
||||
|
||||
item_usage item_get_usage(item_id id) {
|
||||
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
|
||||
return items[id].usage;
|
||||
}
|
||||
|
||||
bool item_get_place_directional(item_id id) {
|
||||
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
|
||||
return items[id].place.directional;
|
||||
}
|
|
@ -1,16 +1,15 @@
|
|||
#pragma once
|
||||
#include "platform/system.h"
|
||||
#include "models/assets.h"
|
||||
#include "gen/assets.h"
|
||||
#include "world/blocks.h"
|
||||
|
||||
#include "models/components.h"
|
||||
#include "ecs/components.h"
|
||||
|
||||
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
|
||||
|
@ -18,17 +17,10 @@ typedef enum {
|
|||
UKIND_PROXY,
|
||||
} item_usage;
|
||||
|
||||
typedef enum {
|
||||
UDATA_NONE,
|
||||
UDATA_ENERGY_SOURCE,
|
||||
} item_attachment;
|
||||
|
||||
typedef struct {
|
||||
asset_id kind;
|
||||
item_usage usage;
|
||||
item_attachment attachment;
|
||||
uint32_t max_quantity;
|
||||
uint8_t has_storage;
|
||||
|
||||
// NOTE(zaklaus): usage data
|
||||
union {
|
||||
|
@ -45,42 +37,22 @@ typedef struct {
|
|||
asset_id id;
|
||||
} place_item;
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
asset_id producer;
|
||||
float energy_level;
|
||||
} energy_source;
|
||||
};
|
||||
|
||||
// NOTE: item data
|
||||
union {
|
||||
struct {
|
||||
uint8_t w;
|
||||
uint8_t h;
|
||||
const asset_id *plan;
|
||||
} blueprint;
|
||||
};
|
||||
} item_desc;
|
||||
|
||||
typedef uint16_t item_id;
|
||||
|
||||
void item_db(void);
|
||||
void item_setup();
|
||||
void item_cleanup();
|
||||
void item_register(item_desc desc);
|
||||
|
||||
// NOTE(zaklaus): item drops
|
||||
void item_show(uint64_t ent, bool show);
|
||||
|
||||
uint64_t item_spawn(asset_id kind, uint32_t qty);
|
||||
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);
|
||||
void item_use(ecs_world_t *ecs, ItemDrop *it, Position p, uint64_t udata);
|
||||
|
||||
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);
|
|
@ -0,0 +1,21 @@
|
|||
#include "ents/items.h"
|
||||
#include "world/entity_view.h"
|
||||
#include "items_list_helpers.h"
|
||||
|
||||
static item_desc *items = 0;
|
||||
|
||||
void item_setup() {
|
||||
item_register((item_desc){ .kind = 0, .max_quantity = 0, });
|
||||
item_register(ITEM_BLOCK(ASSET_DEMO_ICEMAKER, 64, ASSET_WATER));
|
||||
item_register(ITEM_SELF(ASSET_FENCE, 64));
|
||||
item_register(ITEM_SELF(ASSET_WOOD, 64));
|
||||
item_register(ITEM_HOLD(ASSET_TREE, 64));
|
||||
|
||||
item_register(ITEM_SELF_DIR(ASSET_BELT, 999));
|
||||
item_register(ITEM_PROXY(ASSET_BELT_LEFT, ASSET_BELT));
|
||||
item_register(ITEM_PROXY(ASSET_BELT_RIGHT, ASSET_BELT));
|
||||
item_register(ITEM_PROXY(ASSET_BELT_UP, ASSET_BELT));
|
||||
item_register(ITEM_PROXY(ASSET_BELT_DOWN, ASSET_BELT));
|
||||
|
||||
item_register(ITEM_ENT(ASSET_CHEST, 32, ASSET_CHEST));
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#define ITEM_HOLD(asset, qty)\
|
||||
(item_desc){\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_HOLD,\
|
||||
.max_quantity = qty,\
|
||||
}
|
||||
|
||||
#define ITEM_BLOCK(asset, qty, build_asset)\
|
||||
(item_desc){\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_PLACE,\
|
||||
.max_quantity = qty,\
|
||||
.place = {\
|
||||
.kind = build_asset,\
|
||||
}\
|
||||
}
|
||||
|
||||
#define ITEM_BLOCK_DIR(asset, qty, build_asset)\
|
||||
(item_desc){\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_PLACE,\
|
||||
.max_quantity = qty,\
|
||||
.place = {\
|
||||
.kind = build_asset,\
|
||||
.directional = true,\
|
||||
}\
|
||||
}
|
||||
|
||||
#define ITEM_PROXY(asset, proxy_id)\
|
||||
(item_desc){\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_PROXY,\
|
||||
.proxy = {\
|
||||
.id = proxy_id,\
|
||||
}\
|
||||
}
|
||||
|
||||
#define ITEM_ENT(asset, qty, eid)\
|
||||
(item_desc){\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_PLACE_ITEM,\
|
||||
.max_quantity = qty,\
|
||||
.place_item = {\
|
||||
.id = eid\
|
||||
}\
|
||||
}
|
||||
|
||||
#define ITEM_SELF(asset, qty) ITEM_BLOCK(asset, qty, asset)
|
||||
#define ITEM_SELF_DIR(asset, qty) ITEM_BLOCK_DIR(asset, qty, asset)
|
|
@ -0,0 +1,34 @@
|
|||
#include "ents/player.h"
|
||||
#include "ents/entity.h"
|
||||
#include "world/entity_view.h"
|
||||
#include "flecs/flecs.h"
|
||||
#include "librg.h"
|
||||
#include "world/world.h"
|
||||
|
||||
#include "ecs/components.h"
|
||||
#include "ecs/systems.h"
|
||||
#include "zpl.h"
|
||||
|
||||
#define PLAYER_MAX_HP 100.0f
|
||||
|
||||
uint64_t player_spawn(char *name) {
|
||||
ecs_entity_t e = entity_spawn(EKIND_PLAYER);
|
||||
|
||||
if (!name) {
|
||||
name = zpl_bprintf("player_%d", e);
|
||||
}
|
||||
|
||||
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});
|
||||
|
||||
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
|
||||
|
||||
return (uint64_t)e;
|
||||
}
|
||||
|
||||
void player_despawn(uint64_t ent_id) {
|
||||
entity_despawn(ent_id);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include "ents/storage.h"
|
||||
#include "ents/device.h"
|
||||
#include "ents/entity.h"
|
||||
#include "world/entity_view.h"
|
||||
#include "world/world.h"
|
||||
|
||||
#include "ecs/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);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "platform/system.h"
|
||||
|
||||
uint64_t storage_spawn(void);
|
||||
void storage_despawn(uint64_t id);
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include "ents/vehicle.h"
|
||||
#include "ents/entity.h"
|
||||
#include "world/entity_view.h"
|
||||
#include "world/world.h"
|
||||
|
||||
#include "ecs/components.h"
|
||||
|
||||
uint64_t vehicle_spawn(void) {
|
||||
ecs_entity_t e = entity_spawn(EKIND_VEHICLE);
|
||||
|
||||
Vehicle *veh = ecs_get_mut(world_ecs(), e, Vehicle);
|
||||
*veh = (Vehicle){
|
||||
.wheel_base = 50.0f,
|
||||
.speed = 50.0f,
|
||||
.reverse_speed = -20.0f,
|
||||
.force = 0.0f,
|
||||
};
|
||||
return (uint64_t)e;
|
||||
}
|
||||
|
||||
void vehicle_despawn(uint64_t ent_id) {
|
||||
entity_despawn(ent_id);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
#include "platform/system.h"
|
||||
|
||||
uint64_t vehicle_spawn(void);
|
||||
void vehicle_despawn(uint64_t id);
|
||||
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
// use your favorite editor to quickly navigate between various files.
|
||||
|
||||
// 1) Register a new Asset ID
|
||||
#include "models/assets.h"
|
||||
#include "gen/assets.h"
|
||||
|
||||
// 2) Add the asset to the asset list
|
||||
#include "assets_list.c"
|
||||
|
@ -20,3 +20,4 @@
|
|||
|
||||
// NOTE(zaklaus): Register an item
|
||||
#include "items_list.c"
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
#include "gen/assets.h"
|
||||
#include "raylib.h"
|
||||
#include "gen/texgen.h"
|
||||
|
||||
typedef struct {
|
||||
asset_id id;
|
||||
asset_kind kind;
|
||||
|
||||
union {
|
||||
Texture2D tex;
|
||||
Sound snd;
|
||||
};
|
||||
|
||||
// NOTE(zaklaus): metadata
|
||||
} asset;
|
||||
|
||||
#include "assets_list.c"
|
||||
|
||||
#define ASSET_FRAME_RENDER_MS (1.0/5.0)
|
||||
#define ASSET_FRAME_SKIP 4
|
||||
static int64_t assets_resources_frame_counter = 1;
|
||||
static double assets_resources_frame_next_draw = 0.0;
|
||||
|
||||
#include <time.h>
|
||||
|
||||
void assets_register(asset_desc a) {
|
||||
if (!assets) {
|
||||
zpl_array_init(assets, zpl_heap());
|
||||
}
|
||||
|
||||
zpl_array_append(assets, ((asset){ .id = a.id, .kind = a.kind }));
|
||||
}
|
||||
|
||||
void assets_cleanup(void) {
|
||||
zpl_array_free(assets); assets = NULL;
|
||||
}
|
||||
|
||||
int32_t assets_resources_setup(void) {
|
||||
for (zpl_isize i=0; i<zpl_array_count(assets); 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;
|
||||
}
|
||||
}
|
||||
assets_resources_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t assets_resources_frame(void) {
|
||||
if (assets_resources_frame_next_draw < get_cached_time()) {
|
||||
for (zpl_isize i=0; i<zpl_array_count(assets); i++) {
|
||||
asset *b = &assets[i];
|
||||
|
||||
switch (b->kind) {
|
||||
case AKIND_ANIM: {
|
||||
UnloadTexture(b->tex);
|
||||
b->tex = texgen_build_anim(b->id, assets_resources_frame_counter);
|
||||
}break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
assets_resources_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
|
||||
assets_resources_frame_counter += ASSET_FRAME_SKIP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void assets_resources_destroy(void) {
|
||||
for (zpl_isize i=0; i<zpl_array_count(assets); i++) {
|
||||
switch (assets[i].kind) {
|
||||
case AKIND_ANIM:
|
||||
case AKIND_TEXTURE: {
|
||||
UnloadTexture(assets[i].tex);
|
||||
}break;
|
||||
|
||||
case AKIND_SOUND: {
|
||||
// TODO(zaklaus): soundgen
|
||||
}break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t assets_find(asset_id id) {
|
||||
for (zpl_isize i=0; i<zpl_array_count(assets); i++) {
|
||||
if (assets[i].id == id)
|
||||
return i;
|
||||
}
|
||||
|
||||
ZPL_PANIC("Unknown asset id: %d\n", id);
|
||||
return ASSET_INVALID;
|
||||
}
|
||||
|
||||
asset_kind assets_get_kind(uint16_t id) {
|
||||
return assets[id].kind;
|
||||
}
|
||||
|
||||
void *assets_get_snd(uint16_t id) {
|
||||
return (void*)&assets[id].snd;;
|
||||
}
|
||||
|
||||
void *assets_get_tex(uint16_t id) {
|
||||
return (void*)&assets[id].tex;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
#include "platform/system.h"
|
||||
|
||||
#define ASSET_INVALID 0xFF
|
||||
|
||||
#define ASSET_ENTRY(asset, asset_kind)\
|
||||
(asset_desc){\
|
||||
.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)
|
||||
|
||||
typedef enum {
|
||||
// NOTE(zaklaus): Debug
|
||||
ASSET_EMPTY,
|
||||
ASSET_BLANK,
|
||||
ASSET_BUILDMODE_HIGHLIGHT,
|
||||
|
||||
// NOTE(zaklaus): entities
|
||||
ASSET_PLAYER,
|
||||
ASSET_THING,
|
||||
ASSET_CHEST,
|
||||
|
||||
// NOTE(zaklaus): items
|
||||
ASSET_DEMO_ICEMAKER,
|
||||
|
||||
// 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_BELT,
|
||||
ASSET_BELT_LEFT,
|
||||
ASSET_BELT_RIGHT,
|
||||
ASSET_BELT_UP,
|
||||
ASSET_BELT_DOWN,
|
||||
|
||||
ASSET_NEXT_FREE,
|
||||
|
||||
MAX_ASSETS = 1024,
|
||||
} asset_id;
|
||||
|
||||
typedef enum {
|
||||
AKIND_TEXTURE,
|
||||
AKIND_ANIM,
|
||||
AKIND_SOUND,
|
||||
|
||||
FORCE_AKIND_UINT8 = UINT8_MAX
|
||||
} asset_kind;
|
||||
|
||||
typedef struct {
|
||||
asset_id id;
|
||||
asset_kind kind;
|
||||
} asset_desc;
|
||||
|
||||
void assets_setup(void);
|
||||
void assets_cleanup(void);
|
||||
void assets_register(asset_desc desc);
|
||||
|
||||
// resources
|
||||
int32_t assets_resources_setup(void);
|
||||
void assets_resources_destroy(void);
|
||||
int32_t assets_resources_frame(void);
|
||||
|
||||
uint16_t assets_find(asset_id id);
|
||||
|
||||
asset_kind assets_get_kind(uint16_t id);
|
||||
void *assets_get_snd(uint16_t id);
|
||||
void *assets_get_tex(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})
|
|
@ -0,0 +1,31 @@
|
|||
#include "gen/assets.h"
|
||||
|
||||
static asset *assets = 0;
|
||||
|
||||
void assets_setup() {
|
||||
assets_register(ASSET_TEX(ASSET_EMPTY));
|
||||
assets_register(ASSET_TEX(ASSET_BLANK));
|
||||
assets_register(ASSET_TEX(ASSET_BUILDMODE_HIGHLIGHT));
|
||||
assets_register(ASSET_TEX(ASSET_DEMO_ICEMAKER));
|
||||
assets_register(ASSET_TEX(ASSET_CHEST));
|
||||
|
||||
// NOTE: blocks
|
||||
assets_register(ASSET_TEX(ASSET_FENCE));
|
||||
assets_register(ASSET_TEX(ASSET_DEV));
|
||||
assets_register(ASSET_TEX(ASSET_GROUND));
|
||||
assets_register(ASSET_TEX(ASSET_DIRT));
|
||||
assets_register(ASSET_ANI(ASSET_WATER));
|
||||
assets_register(ASSET_TEX(ASSET_LAVA));
|
||||
assets_register(ASSET_TEX(ASSET_WALL));
|
||||
assets_register(ASSET_TEX(ASSET_HILL));
|
||||
assets_register(ASSET_TEX(ASSET_HILL_SNOW));
|
||||
assets_register(ASSET_TEX(ASSET_HOLE));
|
||||
assets_register(ASSET_TEX(ASSET_WOOD));
|
||||
assets_register(ASSET_TEX(ASSET_TREE));
|
||||
|
||||
assets_register(ASSET_TEX(ASSET_BELT));
|
||||
assets_register(ASSET_TEX(ASSET_BELT_LEFT));
|
||||
assets_register(ASSET_TEX(ASSET_BELT_RIGHT));
|
||||
assets_register(ASSET_TEX(ASSET_BELT_UP));
|
||||
assets_register(ASSET_TEX(ASSET_BELT_DOWN));
|
||||
};
|
|
@ -0,0 +1,77 @@
|
|||
#include "gen/texgen.h"
|
||||
#include "world/world.h"
|
||||
#include "texgen_data.c"
|
||||
#include "zpl.h"
|
||||
|
||||
static inline
|
||||
Texture2D LoadTexEco(const char *name) {
|
||||
static char filename[128];
|
||||
zpl_snprintf(filename, 128, "art/gen/%s.png", name);
|
||||
return LoadTexture(filename);
|
||||
}
|
||||
|
||||
static inline
|
||||
Image LoadImageEco(const char *name) {
|
||||
static char filename[128];
|
||||
zpl_snprintf(filename, 128, "art/gen/%s.png", name);
|
||||
return LoadImage(filename);
|
||||
}
|
||||
|
||||
static inline
|
||||
Texture2D Image2TexEco(Image image) {
|
||||
Texture2D tex = LoadTextureFromImage(image);
|
||||
UnloadImage(image);
|
||||
return tex;
|
||||
}
|
||||
|
||||
static inline
|
||||
Texture2D GenColorEco(Color color) {
|
||||
Image img = GenImageColor(1, 1, color);
|
||||
return Image2TexEco(img);
|
||||
}
|
||||
|
||||
Texture2D texgen_build_anim(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);
|
||||
}break;
|
||||
|
||||
default: return GenColorEco(PINK); break;
|
||||
}
|
||||
}
|
||||
|
||||
Texture2D texgen_build_sprite(asset_id id) {
|
||||
switch (id) {
|
||||
case ASSET_BLANK: return GenColorEco(WHITE); break;
|
||||
case ASSET_BUILDMODE_HIGHLIGHT: return GenColorEco(WHITE); break;
|
||||
|
||||
// NOTE(zaklaus): items
|
||||
case ASSET_DEMO_ICEMAKER: return LoadTexEco("demo_icemaker");
|
||||
|
||||
// NOTE(zaklaus): blocks
|
||||
case ASSET_FENCE: return LoadTexEco("fence");
|
||||
case ASSET_GROUND: return LoadTexEco("grass");
|
||||
case ASSET_DIRT: return LoadTexEco("dirt");
|
||||
case ASSET_WALL: return LoadTexEco("asphalt");
|
||||
case ASSET_HILL_SNOW:
|
||||
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_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");
|
||||
|
||||
default: return GenColorEco(PINK); break;
|
||||
}
|
||||
}
|
|
@ -2,11 +2,7 @@
|
|||
#include "platform/system.h"
|
||||
#include "raylib.h"
|
||||
#include "world/blocks.h"
|
||||
#include "models/assets.h"
|
||||
#include "gen/assets.h"
|
||||
|
||||
Texture2D texgen_build_anim(asset_id id, int64_t counter);
|
||||
Texture2D texgen_build_sprite(asset_id id);
|
||||
|
||||
// NOTE(zak): this is a fallback for when the asset is not defined by the game
|
||||
Texture2D texgen_build_anim_fallback(asset_id id, int64_t counter);
|
||||
Texture2D texgen_build_sprite_fallback(asset_id id);
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
// NOTE(zaklaus): contains collection of packed images used by texgen
|
||||
// TODO(zaklaus): we will use files for now
|
|
@ -1,68 +0,0 @@
|
|||
#include "gen/texgen.h"
|
||||
#include "world/world.h"
|
||||
#include "zpl.h"
|
||||
#include "utils/raylib_helpers.h"
|
||||
|
||||
Texture2D texgen_build_anim_fallback(asset_id id, int64_t counter) {
|
||||
(void)counter;
|
||||
switch (id) {
|
||||
case ASSET_WATER: {
|
||||
return LoadTexEco(zpl_bprintf("%s%d", "water", counter%3));
|
||||
}break;
|
||||
|
||||
default: return GenColorEco(PINK); break;
|
||||
}
|
||||
}
|
||||
|
||||
Texture2D texgen_build_sprite_fallback(asset_id id) {
|
||||
switch (id) {
|
||||
case ASSET_BLANK: return GenColorEco(WHITE); break;
|
||||
case ASSET_BUILDMODE_HIGHLIGHT: return GenColorEco(WHITE); break;
|
||||
case ASSET_BLOCK_FRAME: return GenFrameRect(); break;
|
||||
|
||||
// NOTE(zaklaus): items
|
||||
case ASSET_COAL: return LoadTexEco("coal");
|
||||
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");
|
||||
case ASSET_DIRT: return LoadTexEco("dirt");
|
||||
case ASSET_WALL: return LoadTexEco("asphalt");
|
||||
case ASSET_HILL_SNOW:
|
||||
case ASSET_HILL: return LoadTexEco("rock");
|
||||
case ASSET_LAVA: return LoadTexEco("lava");
|
||||
case ASSET_WOOD: return LoadTexEco("wood");
|
||||
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");
|
||||
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);
|
||||
}
|