diff options
| author | untodesu <kirill@untode.su> | 2025-09-12 14:09:34 +0500 |
|---|---|---|
| committer | untodesu <kirill@untode.su> | 2025-09-12 14:09:34 +0500 |
| commit | 73cbcdd6e8c849e32abbf9757e603e6a6654e870 (patch) | |
| tree | 136e1aef82a25c31552b8990952a7607cfd4708e /game | |
| parent | e9076f22fe2a49d1cd8933e54b7b00c5dd943269 (diff) | |
| download | voxelius-73cbcdd6e8c849e32abbf9757e603e6a6654e870.tar.bz2 voxelius-73cbcdd6e8c849e32abbf9757e603e6a6654e870.zip | |
Metaitems
Diffstat (limited to 'game')
| -rw-r--r-- | game/client/experiments.cc | 9 | ||||
| -rw-r--r-- | game/client/game.cc | 4 | ||||
| -rw-r--r-- | game/client/gui/hotbar.cc | 19 | ||||
| -rw-r--r-- | game/client/gui/hotbar.hh | 9 | ||||
| -rw-r--r-- | game/client/gui/status_lines.cc | 4 | ||||
| -rw-r--r-- | game/client/gui/status_lines.hh | 2 | ||||
| -rw-r--r-- | game/client/session.cc | 4 | ||||
| -rw-r--r-- | game/server/sessions.cc | 2 | ||||
| -rw-r--r-- | game/shared/game_items.cc | 91 | ||||
| -rw-r--r-- | game/shared/game_items.hh | 24 | ||||
| -rw-r--r-- | game/shared/game_voxels.cc | 154 | ||||
| -rw-r--r-- | game/shared/world/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | game/shared/world/chunk.cc | 7 | ||||
| -rw-r--r-- | game/shared/world/feature.cc | 7 | ||||
| -rw-r--r-- | game/shared/world/item.cc | 55 | ||||
| -rw-r--r-- | game/shared/world/item.hh | 84 | ||||
| -rw-r--r-- | game/shared/world/item_registry.cc | 101 | ||||
| -rw-r--r-- | game/shared/world/item_registry.hh | 55 | ||||
| -rw-r--r-- | game/shared/world/voxel.cc | 54 | ||||
| -rw-r--r-- | game/shared/world/voxel.hh | 28 | ||||
| -rw-r--r-- | game/shared/world/voxel_registry.cc | 4 |
21 files changed, 373 insertions, 346 deletions
diff --git a/game/client/experiments.cc b/game/client/experiments.cc index b947012..8b0b526 100644 --- a/game/client/experiments.cc +++ b/game/client/experiments.cc @@ -73,9 +73,12 @@ void experiments::attack(void) void experiments::interact(void)
{
- if(auto info = world::item_registry::find(gui::hotbar::slots[gui::hotbar::active_slot])) {
- if(info->place_voxel) {
- globals::dimension->set_voxel(info->place_voxel, world::player_target::coord + world::player_target::normal);
+ auto active_item = gui::hotbar::slots[gui::hotbar::active_slot];
+
+ if(active_item) {
+ if(auto place_voxel = active_item->get_place_voxel()) {
+ globals::dimension->set_voxel(place_voxel, world::player_target::coord + world::player_target::normal);
+ return;
}
}
}
diff --git a/game/client/game.cc b/game/client/game.cc index 257bd2d..d61ce84 100644 --- a/game/client/game.cc +++ b/game/client/game.cc @@ -412,8 +412,8 @@ void client_game::init_late(void) world::voxel_atlas::generate_mipmaps();
- for(std::shared_ptr<world::ItemInfo>& info : world::item_registry::items) {
- info->cached_texture = resource::load<TextureGUI>(info->texture.c_str(), TEXTURE_GUI_LOAD_CLAMP_S | TEXTURE_GUI_LOAD_CLAMP_T);
+ for(auto& item : world::item_registry::items) {
+ item->set_cached_texture(resource::load<TextureGUI>(item->get_texture(), TEXTURE_GUI_LOAD_CLAMP_S | TEXTURE_GUI_LOAD_CLAMP_T));
}
experiments::init_late();
diff --git a/game/client/gui/hotbar.cc b/game/client/gui/hotbar.cc index 806d82b..e9458dd 100644 --- a/game/client/gui/hotbar.cc +++ b/game/client/gui/hotbar.cc @@ -25,7 +25,7 @@ constexpr static float SELECTOR_PADDING = 1.0f; constexpr static float HOTBAR_PADDING = 2.0f;
unsigned int gui::hotbar::active_slot = 0U;
-item_id gui::hotbar::slots[HOTBAR_SIZE];
+std::array<const world::Item*, HOTBAR_SIZE> gui::hotbar::slots = {};
static config::KeyBind hotbar_keys[HOTBAR_SIZE];
@@ -40,14 +40,13 @@ static ImU32 get_color_alpha(ImGuiCol style_color, float alpha) static void update_hotbar_item(void)
{
- if(gui::hotbar::slots[gui::hotbar::active_slot] == NULL_ITEM_ID) {
+ auto current_item = gui::hotbar::slots[gui::hotbar::active_slot];
+
+ if(current_item == nullptr) {
gui::status_lines::unset(gui::STATUS_HOTBAR);
- return;
}
-
- if(auto info = world::item_registry::find(gui::hotbar::slots[gui::hotbar::active_slot])) {
- gui::status_lines::set(gui::STATUS_HOTBAR, info->name, ImVec4(1.0f, 1.0f, 1.0f, 1.0f), 5.0f);
- return;
+ else {
+ gui::status_lines::set(gui::STATUS_HOTBAR, current_item->get_name(), ImVec4(1.0f, 1.0f, 1.0f, 1.0f), 5.0f);
}
}
@@ -154,9 +153,9 @@ void gui::hotbar::layout(void) // Draw individual item textures in the hotbar
for(std::size_t i = 0; i < HOTBAR_SIZE; ++i) {
- const auto info = world::item_registry::find(gui::hotbar::slots[i]);
+ auto item = gui::hotbar::slots[i];
- if((info == nullptr) || (info->cached_texture == nullptr)) {
+ if((item == nullptr) || (item->get_cached_texture() == nullptr)) {
// There's either no item in the slot
// or the item doesn't have a texture
continue;
@@ -164,7 +163,7 @@ void gui::hotbar::layout(void) const auto item_start = ImVec2(background_start.x + i * item_size + item_padding_a, background_start.y + item_padding_a);
const auto item_end = ImVec2(item_start.x + item_size - item_padding_b, item_start.y + item_size - item_padding_b);
- draw_list->AddImage(info->cached_texture->handle, item_start, item_end);
+ draw_list->AddImage(item->get_cached_texture()->handle, item_start, item_end);
}
}
diff --git a/game/client/gui/hotbar.hh b/game/client/gui/hotbar.hh index 88ce791..223dbc9 100644 --- a/game/client/gui/hotbar.hh +++ b/game/client/gui/hotbar.hh @@ -1,16 +1,19 @@ #pragma once
-#include "shared/types.hh"
-
// TODO: design an inventory system and an item
// registry and integrate the hotbar into that system
+namespace world
+{
+class Item;
+} // namespace world
+
constexpr static unsigned int HOTBAR_SIZE = 9U;
namespace gui::hotbar
{
extern unsigned int active_slot;
-extern item_id slots[HOTBAR_SIZE];
+extern std::array<const world::Item*, HOTBAR_SIZE> slots;
} // namespace gui::hotbar
namespace gui::hotbar
diff --git a/game/client/gui/status_lines.cc b/game/client/gui/status_lines.cc index d1a919a..c146478 100644 --- a/game/client/gui/status_lines.cc +++ b/game/client/gui/status_lines.cc @@ -65,11 +65,11 @@ void gui::status_lines::layout(void) }
}
-void gui::status_lines::set(unsigned int line, const std::string& text, const ImVec4& color, float fadeout)
+void gui::status_lines::set(unsigned int line, std::string_view text, const ImVec4& color, float fadeout)
{
line_text_colors[line] = ImVec4(color.x, color.y, color.z, color.w);
line_shadow_colors[line] = ImVec4(color.x * 0.1f, color.y * 0.1f, color.z * 0.1f, color.w);
- line_strings[line] = std::string(text);
+ line_strings[line] = text;
line_spawns[line] = globals::curtime;
line_fadeouts[line] = fadeout;
}
diff --git a/game/client/gui/status_lines.hh b/game/client/gui/status_lines.hh index 7245d68..f694fd3 100644 --- a/game/client/gui/status_lines.hh +++ b/game/client/gui/status_lines.hh @@ -16,6 +16,6 @@ void layout(void); namespace gui::status_lines
{
-void set(unsigned int line, const std::string& text, const ImVec4& color, float fadeout);
+void set(unsigned int line, std::string_view text, const ImVec4& color, float fadeout);
void unset(unsigned int line);
} // namespace gui::status_lines
diff --git a/game/client/session.cc b/game/client/session.cc index c33b4d9..907b789 100644 --- a/game/client/session.cc +++ b/game/client/session.cc @@ -127,7 +127,7 @@ static void on_voxel_set(const world::VoxelSetEvent& event) // FIXME: should we also validate things here or wait for the server to do so
protocol::SetVoxel packet;
packet.vpos = coord::to_voxel(event.cpos, event.lpos);
- packet.voxel = event.voxel->get_id();
+ packet.voxel = event.voxel ? event.voxel->get_id() : NULL_VOXEL_ID;
protocol::send(session::peer, protocol::encode(packet));
}
@@ -286,7 +286,7 @@ void session::send_login_request(void) protocol::LoginRequest packet;
packet.version = protocol::VERSION;
packet.voxel_registry_checksum = world::voxel_registry::get_checksum();
- packet.item_registry_checksum = world::item_registry::calculate_checksum();
+ packet.item_registry_checksum = world::item_registry::get_checksum();
packet.password_hash = server_password_hash;
packet.username = client_game::username.get();
diff --git a/game/server/sessions.cc b/game/server/sessions.cc index 32b96a3..2ab9d74 100644 --- a/game/server/sessions.cc +++ b/game/server/sessions.cc @@ -72,7 +72,7 @@ static void on_login_request_packet(const protocol::LoginRequest& packet) return;
}
- if(packet.item_registry_checksum != world::item_registry::calculate_checksum()) {
+ if(packet.item_registry_checksum != world::item_registry::get_checksum()) {
protocol::Disconnect response;
response.reason = "protocol.item_registry_checksum";
protocol::send(packet.peer, protocol::encode(response));
diff --git a/game/shared/game_items.cc b/game/shared/game_items.cc index 6073117..cad73da 100644 --- a/game/shared/game_items.cc +++ b/game/shared/game_items.cc @@ -6,61 +6,60 @@ #include "shared/game_voxels.hh"
-item_id game_items::stone = NULL_ITEM_ID;
-item_id game_items::cobblestone = NULL_ITEM_ID;
-item_id game_items::dirt = NULL_ITEM_ID;
-item_id game_items::grass = NULL_ITEM_ID;
-item_id game_items::oak_leaves = NULL_ITEM_ID;
-item_id game_items::oak_planks = NULL_ITEM_ID;
-item_id game_items::oak_log = NULL_ITEM_ID;
-item_id game_items::glass = NULL_ITEM_ID;
-item_id game_items::slime = NULL_ITEM_ID;
-item_id game_items::mud = NULL_ITEM_ID;
+const world::Item* game_items::stone = nullptr;
+const world::Item* game_items::cobblestone = nullptr;
+const world::Item* game_items::dirt = nullptr;
+const world::Item* game_items::grass = nullptr;
+const world::Item* game_items::oak_leaves = nullptr;
+const world::Item* game_items::oak_planks = nullptr;
+const world::Item* game_items::oak_log = nullptr;
+const world::Item* game_items::glass = nullptr;
+const world::Item* game_items::slime = nullptr;
void game_items::populate(void)
{
- // Stone; a hardened slate rock
- game_items::stone =
- world::item_registry::construct("stone").set_texture("textures/item/stone.png").set_place_voxel(game_voxels::stone).build();
+ auto stone_builder = world::ItemBuilder("stone");
+ stone_builder.set_texture("textures/item/stone.png");
+ stone_builder.set_place_voxel(game_voxels::stone);
+ stone = world::item_registry::register_item(stone_builder);
- // Cobblestone; a bunch of small stones
- game_items::cobblestone = world::item_registry::construct("cobblestone")
- .set_texture("textures/item/cobblestone.png")
- .set_place_voxel(game_voxels::cobblestone)
- .build();
+ auto cobblestone_builder = world::ItemBuilder("cobblestone");
+ cobblestone_builder.set_texture("textures/item/cobblestone.png");
+ cobblestone_builder.set_place_voxel(game_voxels::cobblestone);
+ cobblestone = world::item_registry::register_item(cobblestone_builder);
- // Dirt; it's very dirty
- game_items::dirt =
- world::item_registry::construct("dirt").set_texture("textures/item/dirt.png").set_place_voxel(game_voxels::dirt).build();
+ auto dirt_builder = world::ItemBuilder("dirt");
+ dirt_builder.set_texture("textures/item/dirt.png");
+ dirt_builder.set_place_voxel(game_voxels::dirt);
+ dirt = world::item_registry::register_item(dirt_builder);
- // Grass; literally just grassy dirt
- game_items::grass =
- world::item_registry::construct("grass").set_texture("textures/item/grass.png").set_place_voxel(game_voxels::grass).build();
+ auto grass_builder = world::ItemBuilder("grass");
+ grass_builder.set_texture("textures/item/grass.png");
+ grass_builder.set_place_voxel(game_voxels::grass);
+ grass = world::item_registry::register_item(grass_builder);
- // Oak leaves; they're bushy!
- game_items::oak_leaves = world::item_registry::construct("oak_leaves")
- .set_texture("textures/item/oak_leaves.png")
- .set_place_voxel(game_voxels::oak_leaves)
- .build();
+ auto oak_leaves_builder = world::ItemBuilder("oak_leaves");
+ oak_leaves_builder.set_texture("textures/item/oak_leaves.png");
+ oak_leaves_builder.set_place_voxel(game_voxels::oak_leaves);
+ oak_leaves = world::item_registry::register_item(oak_leaves_builder);
- // Oak planks; watch for splinters!
- game_items::oak_planks = world::item_registry::construct("oak_planks")
- .set_texture("textures/item/oak_planks.png")
- .set_place_voxel(game_voxels::oak_planks)
- .build();
+ auto oak_planks_builder = world::ItemBuilder("oak_planks");
+ oak_planks_builder.set_texture("textures/item/oak_planks.png");
+ oak_planks_builder.set_place_voxel(game_voxels::oak_planks);
+ oak_planks = world::item_registry::register_item(oak_planks_builder);
- // Oak log; a big wad of wood
- game_items::oak_log =
- world::item_registry::construct("oak_log").set_texture("textures/item/oak_log.png").set_place_voxel(game_voxels::oak_log).build();
+ auto oak_log_builder = world::ItemBuilder("oak_log");
+ oak_log_builder.set_texture("textures/item/oak_log.png");
+ oak_log_builder.set_place_voxel(game_voxels::oak_log);
+ oak_log = world::item_registry::register_item(oak_log_builder);
- // Glass; used for windowing
- game_items::glass =
- world::item_registry::construct("glass").set_texture("textures/item/glass.png").set_place_voxel(game_voxels::glass).build();
+ auto glass_builder = world::ItemBuilder("glass");
+ glass_builder.set_texture("textures/item/glass.png");
+ glass_builder.set_place_voxel(game_voxels::glass);
+ glass = world::item_registry::register_item(glass_builder);
- // Slime; it's bouncy!
- game_items::slime =
- world::item_registry::construct("slime").set_texture("textures/item/slime.png").set_place_voxel(game_voxels::slime).build();
-
- // Mud; you sink in it!
- game_items::mud = world::item_registry::construct("mud").set_texture("textures/item/mud.png").build();
+ auto slime_builder = world::ItemBuilder("slime");
+ slime_builder.set_texture("textures/item/slime.png");
+ slime_builder.set_place_voxel(game_voxels::slime);
+ slime = world::item_registry::register_item(slime_builder);
}
diff --git a/game/shared/game_items.hh b/game/shared/game_items.hh index 099923f..88952fc 100644 --- a/game/shared/game_items.hh +++ b/game/shared/game_items.hh @@ -2,20 +2,22 @@ #define SHARED_GAME_ITEMS 1
#pragma once
-#include "shared/types.hh"
+namespace world
+{
+class Item;
+} // namespace world
namespace game_items
{
-extern item_id stone;
-extern item_id cobblestone;
-extern item_id dirt;
-extern item_id grass;
-extern item_id oak_leaves;
-extern item_id oak_planks;
-extern item_id oak_log;
-extern item_id glass;
-extern item_id slime;
-extern item_id mud;
+extern const world::Item* stone;
+extern const world::Item* cobblestone;
+extern const world::Item* dirt;
+extern const world::Item* grass;
+extern const world::Item* oak_leaves;
+extern const world::Item* oak_planks;
+extern const world::Item* oak_log;
+extern const world::Item* glass;
+extern const world::Item* slime;
} // namespace game_items
namespace game_items
diff --git a/game/shared/game_voxels.cc b/game/shared/game_voxels.cc index 75c56c7..f262c23 100644 --- a/game/shared/game_voxels.cc +++ b/game/shared/game_voxels.cc @@ -61,81 +61,81 @@ static void dirt_tick(world::Dimension* dimension, const voxel_pos& vpos) void game_voxels::populate(void)
{
- world::VoxelBuilder builder;
-
- builder = world::VoxelBuilder("stone");
- builder.add_default_texture("textures/voxel/stone_01.png")
- .add_default_texture("textures/voxel/stone_02.png")
- .add_default_texture("textures/voxel/stone_03.png")
- .add_default_texture("textures/voxel/stone_04.png");
- stone = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("cobblestone");
- builder.add_default_texture("textures/voxel/cobblestone_01.png").add_default_texture("textures/voxel/cobblestone_02.png");
- cobblestone = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("dirt");
- builder.add_default_texture("textures/voxel/dirt_01.png")
- .add_default_texture("textures/voxel/dirt_02.png")
- .add_default_texture("textures/voxel/dirt_03.png")
- .add_default_texture("textures/voxel/dirt_04.png");
- builder.set_surface_material(world::VMAT_DIRT);
- builder.set_on_tick(&dirt_tick);
- dirt = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("grass");
- builder.add_default_texture("textures/voxel/grass_side_01.png")
- .add_default_texture("textures/voxel/grass_side_02.png")
- .add_face_texture(world::VFACE_BOTTOM, "textures/voxel/dirt_01.png")
- .add_face_texture(world::VFACE_BOTTOM, "textures/voxel/dirt_02.png")
- .add_face_texture(world::VFACE_BOTTOM, "textures/voxel/dirt_03.png")
- .add_face_texture(world::VFACE_BOTTOM, "textures/voxel/dirt_04.png")
- .add_face_texture(world::VFACE_TOP, "textures/voxel/grass_01.png")
- .add_face_texture(world::VFACE_TOP, "textures/voxel/grass_02.png");
- builder.set_surface_material(world::VMAT_GRASS);
- grass = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("vtest");
- builder.add_default_texture("textures/voxel/vtest_F1.png")
- .add_default_texture("textures/voxel/vtest_F2.png")
- .add_default_texture("textures/voxel/vtest_F3.png")
- .add_default_texture("textures/voxel/vtest_F4.png");
- builder.set_animated(true);
- vtest = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("vtest_ck");
- builder.add_default_texture("textures/voxel/chromakey.png");
- vtest_ck = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("oak_leaves");
- builder.add_default_texture("textures/voxel/oak_leaves.png");
- builder.set_render_mode(world::VRENDER_BLEND);
- builder.set_surface_material(world::VMAT_GRASS);
- oak_leaves = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("oak_planks");
- builder.add_default_texture("textures/voxel/oak_planks_01.png").add_default_texture("textures/voxel/oak_planks_02.png");
- builder.set_surface_material(world::VMAT_WOOD);
- oak_planks = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("oak_log");
- builder.add_default_texture("textures/voxel/oak_wood_01.png")
- .add_default_texture("textures/voxel/oak_wood_02.png")
- .add_face_texture(world::VFACE_BOTTOM, "textures/voxel/oak_wood_top.png")
- .add_face_texture(world::VFACE_TOP, "textures/voxel/oak_wood_top.png");
- builder.set_surface_material(world::VMAT_WOOD);
- oak_log = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("glass");
- builder.add_default_texture("textures/voxel/glass_01.png");
- builder.set_render_mode(world::VRENDER_BLEND);
- builder.set_surface_material(world::VMAT_GLASS);
- glass = world::voxel_registry::register_voxel(builder);
-
- builder = world::VoxelBuilder("slime");
- builder.add_default_texture("textures/voxel/slime_01.png");
- builder.set_render_mode(world::VRENDER_BLEND);
- builder.set_surface_material(world::VMAT_SLOSH);
- builder.set_touch_type(world::VTOUCH_BOUNCE).set_touch_values({ 0.00f, 0.60f, 0.00f });
- slime = world::voxel_registry::register_voxel(builder);
+ auto stone_builder = world::VoxelBuilder("stone");
+ stone_builder.add_default_texture("textures/voxel/stone_01.png");
+ stone_builder.add_default_texture("textures/voxel/stone_02.png");
+ stone_builder.add_default_texture("textures/voxel/stone_03.png");
+ stone_builder.add_default_texture("textures/voxel/stone_04.png");
+ stone = world::voxel_registry::register_voxel(stone_builder);
+
+ auto cobblestone_builder = world::VoxelBuilder("cobblestone");
+ cobblestone_builder.add_default_texture("textures/voxel/cobblestone_01.png");
+ cobblestone_builder.add_default_texture("textures/voxel/cobblestone_02.png");
+ cobblestone = world::voxel_registry::register_voxel(cobblestone_builder);
+
+ auto dirt_builder = world::VoxelBuilder("dirt");
+ dirt_builder.add_default_texture("textures/voxel/dirt_01.png");
+ dirt_builder.add_default_texture("textures/voxel/dirt_02.png");
+ dirt_builder.add_default_texture("textures/voxel/dirt_03.png");
+ dirt_builder.add_default_texture("textures/voxel/dirt_04.png");
+ dirt_builder.set_surface_material(world::VMAT_DIRT);
+ dirt_builder.set_on_tick(&dirt_tick);
+ dirt = world::voxel_registry::register_voxel(dirt_builder);
+
+ auto grass_builder = world::VoxelBuilder("grass");
+ grass_builder.add_default_texture("textures/voxel/grass_side_01.png");
+ grass_builder.add_default_texture("textures/voxel/grass_side_02.png");
+ grass_builder.add_face_texture(world::VFACE_BOTTOM, "textures/voxel/dirt_01.png");
+ grass_builder.add_face_texture(world::VFACE_BOTTOM, "textures/voxel/dirt_02.png");
+ grass_builder.add_face_texture(world::VFACE_BOTTOM, "textures/voxel/dirt_03.png");
+ grass_builder.add_face_texture(world::VFACE_BOTTOM, "textures/voxel/dirt_04.png");
+ grass_builder.add_face_texture(world::VFACE_TOP, "textures/voxel/grass_01.png");
+ grass_builder.add_face_texture(world::VFACE_TOP, "textures/voxel/grass_02.png");
+ grass_builder.set_surface_material(world::VMAT_GRASS);
+ grass = world::voxel_registry::register_voxel(grass_builder);
+
+ auto vtest_builder = world::VoxelBuilder("vtest");
+ vtest_builder.add_default_texture("textures/voxel/vtest_F1.png");
+ vtest_builder.add_default_texture("textures/voxel/vtest_F2.png");
+ vtest_builder.add_default_texture("textures/voxel/vtest_F3.png");
+ vtest_builder.add_default_texture("textures/voxel/vtest_F4.png");
+ vtest_builder.set_animated(true);
+ vtest = world::voxel_registry::register_voxel(vtest_builder);
+
+ auto vtest_ck_builder = world::VoxelBuilder("vtest_ck");
+ vtest_ck_builder.add_default_texture("textures/voxel/chromakey.png");
+ vtest_ck = world::voxel_registry::register_voxel(vtest_ck_builder);
+
+ auto oak_leaves_builder = world::VoxelBuilder("oak_leaves");
+ oak_leaves_builder.add_default_texture("textures/voxel/oak_leaves.png");
+ oak_leaves_builder.set_surface_material(world::VMAT_GRASS);
+ oak_leaves = world::voxel_registry::register_voxel(oak_leaves_builder);
+
+ auto oak_planks_builder = world::VoxelBuilder("oak_planks");
+ oak_planks_builder.add_default_texture("textures/voxel/oak_planks_01.png");
+ oak_planks_builder.add_default_texture("textures/voxel/oak_planks_02.png");
+ oak_planks_builder.set_surface_material(world::VMAT_WOOD);
+ oak_planks = world::voxel_registry::register_voxel(oak_planks_builder);
+
+ auto oak_log_builder = world::VoxelBuilder("oak_log");
+ oak_log_builder.add_default_texture("textures/voxel/oak_wood_01.png");
+ oak_log_builder.add_default_texture("textures/voxel/oak_wood_02.png");
+ oak_log_builder.add_face_texture(world::VFACE_BOTTOM, "textures/voxel/oak_wood_top.png");
+ oak_log_builder.add_face_texture(world::VFACE_TOP, "textures/voxel/oak_wood_top.png");
+ oak_log_builder.set_surface_material(world::VMAT_WOOD);
+ oak_log = world::voxel_registry::register_voxel(oak_log_builder);
+
+ auto glass_builder = world::VoxelBuilder("glass");
+ glass_builder.add_default_texture("textures/voxel/glass_01.png");
+ glass_builder.set_render_mode(world::VRENDER_BLEND);
+ glass_builder.set_surface_material(world::VMAT_GLASS);
+ glass = world::voxel_registry::register_voxel(glass_builder);
+
+ auto slime_builder = world::VoxelBuilder("slime");
+ slime_builder.add_default_texture("textures/voxel/slime_01.png");
+ slime_builder.set_render_mode(world::VRENDER_BLEND);
+ slime_builder.set_surface_material(world::VMAT_SLOSH);
+ slime_builder.set_touch_type(world::VTOUCH_BOUNCE);
+ slime_builder.set_touch_values({ 0.00f, 0.60f, 0.00f });
+ slime = world::voxel_registry::register_voxel(slime_builder);
}
diff --git a/game/shared/world/CMakeLists.txt b/game/shared/world/CMakeLists.txt index cc7ed90..db3f370 100644 --- a/game/shared/world/CMakeLists.txt +++ b/game/shared/world/CMakeLists.txt @@ -8,6 +8,8 @@ target_sources(shared PRIVATE "${CMAKE_CURRENT_LIST_DIR}/feature.hh" "${CMAKE_CURRENT_LIST_DIR}/item_registry.cc" "${CMAKE_CURRENT_LIST_DIR}/item_registry.hh" + "${CMAKE_CURRENT_LIST_DIR}/item.cc" + "${CMAKE_CURRENT_LIST_DIR}/item.hh" "${CMAKE_CURRENT_LIST_DIR}/ray_dda.cc" "${CMAKE_CURRENT_LIST_DIR}/ray_dda.hh" "${CMAKE_CURRENT_LIST_DIR}/voxel_registry.cc" diff --git a/game/shared/world/chunk.cc b/game/shared/world/chunk.cc index b1b19a6..f8f7b93 100644 --- a/game/shared/world/chunk.cc +++ b/game/shared/world/chunk.cc @@ -36,12 +36,7 @@ void world::Chunk::set_voxel(const Voxel* voxel, const local_pos& lpos) void world::Chunk::set_voxel(const Voxel* voxel, const std::size_t index)
{
if(index < CHUNK_VOLUME) {
- if(voxel == nullptr) {
- m_voxels[index] = NULL_VOXEL_ID;
- return;
- }
-
- m_voxels[index] = voxel->get_id();
+ m_voxels[index] = voxel ? voxel->get_id() : NULL_VOXEL_ID;
return;
}
}
diff --git a/game/shared/world/feature.cc b/game/shared/world/feature.cc index e704ced..8fe95f1 100644 --- a/game/shared/world/feature.cc +++ b/game/shared/world/feature.cc @@ -69,12 +69,7 @@ void world::Feature::place(const voxel_pos& vpos, const chunk_pos& cpos, VoxelSt continue;
}
- if(voxel == nullptr) {
- voxels[it_index] = NULL_VOXEL_ID;
- }
- else {
- voxels[it_index] = voxel->get_id();
- }
+ voxels[it_index] = voxel ? voxel->get_id() : NULL_VOXEL_ID;
}
}
}
diff --git a/game/shared/world/item.cc b/game/shared/world/item.cc new file mode 100644 index 0000000..5e60609 --- /dev/null +++ b/game/shared/world/item.cc @@ -0,0 +1,55 @@ +#include "shared/pch.hh" + +#include "shared/world/item.hh" + +#include "core/math/crc64.hh" + +#include "shared/world/voxel.hh" + +world::Item::Item(const Item& source, item_id id) noexcept : Item(source) +{ + m_id = id; +} + +void world::Item::set_cached_texture(resource_ptr<TextureGUI> texture) const noexcept +{ + m_cached_texture = std::move(texture); +} + +std::uint64_t world::Item::get_checksum(std::uint64_t combine) const +{ + combine = math::crc64(m_name.data(), m_name.size(), combine); + combine = math::crc64(m_texture.data(), m_texture.size(), combine); + + std::uint32_t id = m_place_voxel ? m_place_voxel->get_id() : NULL_VOXEL_ID; + combine = math::crc64(&id, sizeof(id), combine); + + return combine; +} + +world::ItemBuilder::ItemBuilder(std::string_view name) +{ + set_name(name); +} + +void world::ItemBuilder::set_name(std::string_view name) +{ + assert(name.size()); + + m_name = name; +} + +void world::ItemBuilder::set_texture(std::string_view texture) +{ + m_texture = texture; +} + +void world::ItemBuilder::set_place_voxel(const Voxel* place_voxel) +{ + m_place_voxel = place_voxel; +} + +std::unique_ptr<world::Item> world::ItemBuilder::build(item_id id) const +{ + return std::make_unique<Item>(*this, id); +} diff --git a/game/shared/world/item.hh b/game/shared/world/item.hh new file mode 100644 index 0000000..ffa7f5c --- /dev/null +++ b/game/shared/world/item.hh @@ -0,0 +1,84 @@ +#pragma once + +#include "core/resource/resource.hh" + +#include "shared/types.hh" + +// This resource is only defined client-side and +// resource_ptr<TextureGUI> should remain set to null +// anywhere else in the shared and server code +struct TextureGUI; + +namespace world +{ +class Voxel; +} // namespace world + +namespace world +{ +class Item { +public: + Item(void) = default; + explicit Item(const Item& source, item_id id) noexcept; + + constexpr std::string_view get_name(void) const noexcept; + constexpr item_id get_id(void) const noexcept; + + constexpr std::string_view get_texture(void) const noexcept; + constexpr const Voxel* get_place_voxel(void) const noexcept; + + constexpr resource_ptr<TextureGUI>& get_cached_texture(void) const noexcept; + void set_cached_texture(resource_ptr<TextureGUI> texture) const noexcept; + + std::uint64_t get_checksum(std::uint64_t combine = 0U) const; + +protected: + std::string m_name; + item_id m_id { NULL_ITEM_ID }; + + std::string m_texture; + const Voxel* m_place_voxel { nullptr }; + + mutable resource_ptr<TextureGUI> m_cached_texture; // Client-side only +}; +} // namespace world + +namespace world +{ +class ItemBuilder final : public Item { +public: + explicit ItemBuilder(std::string_view name); + + void set_name(std::string_view name); + + void set_texture(std::string_view texture); + void set_place_voxel(const Voxel* place_voxel); + + std::unique_ptr<Item> build(item_id id) const; +}; +} // namespace world + +constexpr std::string_view world::Item::get_name(void) const noexcept +{ + return m_name; +} + +constexpr item_id world::Item::get_id(void) const noexcept +{ + return m_id; +} + +constexpr std::string_view world::Item::get_texture(void) const noexcept +{ + return m_texture; +} + +constexpr const world::Voxel* world::Item::get_place_voxel(void) const noexcept +{ + return m_place_voxel; +} + +constexpr resource_ptr<TextureGUI>& world::Item::get_cached_texture(void) const noexcept +{ + return m_cached_texture; +} diff --git a/game/shared/world/item_registry.cc b/game/shared/world/item_registry.cc index 783c85e..4e0932c 100644 --- a/game/shared/world/item_registry.cc +++ b/game/shared/world/item_registry.cc @@ -6,104 +6,63 @@ #include "shared/world/voxel_registry.hh"
-std::unordered_map<std::string, world::ItemInfoBuilder> world::item_registry::builders = {};
+static std::uint64_t registry_checksum = 0U;
std::unordered_map<std::string, item_id> world::item_registry::names = {};
-std::vector<std::shared_ptr<world::ItemInfo>> world::item_registry::items = {};
+std::vector<std::unique_ptr<world::Item>> world::item_registry::items = {};
-world::ItemInfoBuilder::ItemInfoBuilder(std::string_view name)
+static void recalculate_checksum(void)
{
- prototype.name = name;
- prototype.texture = std::string();
- prototype.place_voxel = nullptr;
- prototype.cached_texture = nullptr;
-}
+ registry_checksum = 0U;
-world::ItemInfoBuilder& world::ItemInfoBuilder::set_texture(std::string_view texture)
-{
- prototype.texture = texture;
- prototype.cached_texture = nullptr;
- return *this;
+ for(const auto& item : world::item_registry::items) {
+ registry_checksum = item->get_checksum(registry_checksum);
+ }
}
-world::ItemInfoBuilder& world::ItemInfoBuilder::set_place_voxel(const Voxel* place_voxel)
+world::Item* world::item_registry::register_item(const ItemBuilder& builder)
{
- prototype.place_voxel = place_voxel;
- return *this;
-}
+ assert(builder.get_name().size());
+ assert(nullptr == find(builder.get_name()));
-item_id world::ItemInfoBuilder::build(void) const
-{
- const auto it = world::item_registry::names.find(prototype.name);
+ const auto id = static_cast<item_id>(1 + items.size());
- if(it != world::item_registry::names.cend()) {
- spdlog::warn("item_registry: cannot build {}: name already present", prototype.name);
- return it->second;
- }
+ std::unique_ptr<Item> item(builder.build(id));
+ names.emplace(std::string(builder.get_name()), id);
+ items.push_back(std::move(item));
- auto new_info = std::make_shared<ItemInfo>();
- new_info->name = prototype.name;
- new_info->texture = prototype.texture;
- new_info->place_voxel = prototype.place_voxel;
- new_info->cached_texture = nullptr;
+ recalculate_checksum();
- world::item_registry::items.push_back(new_info);
- world::item_registry::names.insert_or_assign(prototype.name, static_cast<item_id>(world::item_registry::items.size()));
-
- return static_cast<item_id>(world::item_registry::items.size());
+ return items.back().get();
}
-world::ItemInfoBuilder& world::item_registry::construct(std::string_view name)
+world::Item* world::item_registry::find(std::string_view name)
{
- const auto it = world::item_registry::builders.find(std::string(name));
-
- if(it != world::item_registry::builders.cend()) {
- return it->second;
- }
- else {
- return world::item_registry::builders.emplace(std::string(name), ItemInfoBuilder(name)).first->second;
- }
-}
+ const auto it = names.find(std::string(name));
-world::ItemInfo* world::item_registry::find(std::string_view name)
-{
- const auto it = world::item_registry::names.find(std::string(name));
-
- if(it != world::item_registry::names.cend()) {
- return world::item_registry::find(it->second);
- }
- else {
+ if(it == names.end()) {
return nullptr;
}
+
+ return items[it->second - 1].get();
}
-world::ItemInfo* world::item_registry::find(const item_id item)
+world::Item* world::item_registry::find(const item_id item)
{
- if((item != NULL_ITEM_ID) && (item <= world::item_registry::items.size())) {
- return world::item_registry::items[item - 1].get();
- }
- else {
+ if(item == NULL_ITEM_ID || item > items.size()) {
return nullptr;
}
+
+ return items[item - 1].get();
}
void world::item_registry::purge(void)
{
- world::item_registry::builders.clear();
- world::item_registry::names.clear();
- world::item_registry::items.clear();
+ registry_checksum = 0U;
+ items.clear();
+ names.clear();
}
-std::uint64_t world::item_registry::calculate_checksum(void)
+std::uint64_t world::item_registry::get_checksum(void)
{
- std::uint64_t result = 0;
-
- for(const auto& info : world::item_registry::items) {
- result = math::crc64(info->name, result);
-
- if(info->place_voxel) {
- result += static_cast<std::uint64_t>(info->place_voxel->get_id());
- }
- }
-
- return result;
+ return registry_checksum;
}
diff --git a/game/shared/world/item_registry.hh b/game/shared/world/item_registry.hh index 2274da2..b4c9fda 100644 --- a/game/shared/world/item_registry.hh +++ b/game/shared/world/item_registry.hh @@ -1,61 +1,18 @@ #pragma once
-#include "core/resource/resource.hh"
-
-#include "shared/types.hh"
-
-// This resource is only defined client-side and
-// resource_ptr<TextureGUI> should remain set to null
-// anywhere else in the shared and server code
-struct TextureGUI;
-
-namespace world
-{
-class Voxel;
-} // namespace world
-
-namespace world
-{
-struct ItemInfo final {
- std::string name;
- std::string texture;
- const Voxel* place_voxel;
-
- resource_ptr<TextureGUI> cached_texture; // Client-side only
-};
-} // namespace world
-
-namespace world
-{
-class ItemInfoBuilder final {
-public:
- explicit ItemInfoBuilder(std::string_view name);
- virtual ~ItemInfoBuilder(void) = default;
-
-public:
- ItemInfoBuilder& set_texture(std::string_view texture);
- ItemInfoBuilder& set_place_voxel(const Voxel* place_voxel);
-
-public:
- item_id build(void) const;
-
-private:
- ItemInfo prototype;
-};
-} // namespace world
+#include "shared/world/item.hh"
namespace world::item_registry
{
-extern std::unordered_map<std::string, ItemInfoBuilder> builders;
extern std::unordered_map<std::string, item_id> names;
-extern std::vector<std::shared_ptr<ItemInfo>> items;
+extern std::vector<std::unique_ptr<Item>> items;
} // namespace world::item_registry
namespace world::item_registry
{
-ItemInfoBuilder& construct(std::string_view name);
-ItemInfo* find(std::string_view name);
-ItemInfo* find(const item_id item);
+Item* register_item(const ItemBuilder& builder);
+Item* find(std::string_view name);
+Item* find(const item_id item);
} // namespace world::item_registry
namespace world::item_registry
@@ -65,5 +22,5 @@ void purge(void); namespace world::item_registry
{
-std::uint64_t calculate_checksum(void);
+std::uint64_t get_checksum(void);
} // namespace world::item_registry
diff --git a/game/shared/world/voxel.cc b/game/shared/world/voxel.cc index 1cd1504..21fe62c 100644 --- a/game/shared/world/voxel.cc +++ b/game/shared/world/voxel.cc @@ -55,7 +55,7 @@ void world::Voxel::set_face_cache(VoxelFace face, std::size_t offset, std::size_ m_cached_face_planes[face] = plane; } -std::uint64_t world::Voxel::calculate_checksum(std::uint64_t combine) const +std::uint64_t world::Voxel::get_checksum(std::uint64_t combine) const { combine = math::crc64(m_name.data(), m_name.size(), combine); combine += static_cast<std::uint64_t>(m_shape); @@ -68,102 +68,76 @@ world::VoxelBuilder::VoxelBuilder(std::string_view name) set_name(name); } -world::VoxelBuilder& world::VoxelBuilder::set_on_place(VoxelOnPlaceFunc func) noexcept +void world::VoxelBuilder::set_on_place(VoxelOnPlaceFunc func) noexcept { m_on_place = std::move(func); - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_on_remove(VoxelOnRemoveFunc func) noexcept +void world::VoxelBuilder::set_on_remove(VoxelOnRemoveFunc func) noexcept { m_on_remove = std::move(func); - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_on_tick(VoxelOnTickFunc func) noexcept +void world::VoxelBuilder::set_on_tick(VoxelOnTickFunc func) noexcept { m_on_tick = std::move(func); - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_name(std::string_view name) noexcept +void world::VoxelBuilder::set_name(std::string_view name) noexcept { assert(name.size()); m_name = name; - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_render_mode(VoxelRender mode) noexcept +void world::VoxelBuilder::set_render_mode(VoxelRender mode) noexcept { m_render_mode = mode; - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_shape(VoxelShape shape) noexcept +void world::VoxelBuilder::set_shape(VoxelShape shape) noexcept { m_shape = shape; - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_animated(bool animated) noexcept +void world::VoxelBuilder::set_animated(bool animated) noexcept { m_animated = animated; - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_touch_type(VoxelTouch type) noexcept +void world::VoxelBuilder::set_touch_type(VoxelTouch type) noexcept { m_touch_type = type; - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_touch_values(const glm::fvec3& values) noexcept +void world::VoxelBuilder::set_touch_values(const glm::fvec3& values) noexcept { m_touch_values = values; - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_surface_material(VoxelMaterial material) noexcept +void world::VoxelBuilder::set_surface_material(VoxelMaterial material) noexcept { m_surface_material = material; - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::set_collision(const math::AABBf& box) noexcept +void world::VoxelBuilder::set_collision(const math::AABBf& box) noexcept { m_collision = box; - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::add_default_texture(std::string_view path) +void world::VoxelBuilder::add_default_texture(std::string_view path) { assert(path.size()); m_default_textures.emplace_back(path); - - return *this; } -world::VoxelBuilder& world::VoxelBuilder::add_face_texture(VoxelFace face, std::string_view path) +void world::VoxelBuilder::add_face_texture(VoxelFace face, std::string_view path) { assert(face < m_face_textures.size()); assert(path.size()); m_face_textures[face].emplace_back(path); - - return *this; } std::unique_ptr<world::Voxel> world::VoxelBuilder::build(voxel_id id) const diff --git a/game/shared/world/voxel.hh b/game/shared/world/voxel.hh index 9cc0e4c..6013962 100644 --- a/game/shared/world/voxel.hh +++ b/game/shared/world/voxel.hh @@ -129,7 +129,7 @@ public: /// Calculate a checksum for the voxel's properties /// @param combine An optional initial checksum to combine with /// @return The calculated checksum - std::uint64_t calculate_checksum(std::uint64_t combine = 0U) const; + std::uint64_t get_checksum(std::uint64_t combine = 0U) const; protected: std::string m_name; @@ -163,24 +163,24 @@ public: VoxelBuilder(void) = default; explicit VoxelBuilder(std::string_view name); - VoxelBuilder& set_on_place(VoxelOnPlaceFunc func) noexcept; - VoxelBuilder& set_on_remove(VoxelOnRemoveFunc func) noexcept; - VoxelBuilder& set_on_tick(VoxelOnTickFunc func) noexcept; + void set_on_place(VoxelOnPlaceFunc func) noexcept; + void set_on_remove(VoxelOnRemoveFunc func) noexcept; + void set_on_tick(VoxelOnTickFunc func) noexcept; - VoxelBuilder& set_name(std::string_view name) noexcept; + void set_name(std::string_view name) noexcept; - VoxelBuilder& set_render_mode(VoxelRender mode) noexcept; - VoxelBuilder& set_shape(VoxelShape shape) noexcept; - VoxelBuilder& set_animated(bool animated) noexcept; + void set_render_mode(VoxelRender mode) noexcept; + void set_shape(VoxelShape shape) noexcept; + void set_animated(bool animated) noexcept; - VoxelBuilder& set_touch_type(VoxelTouch type) noexcept; - VoxelBuilder& set_touch_values(const glm::fvec3& values) noexcept; - VoxelBuilder& set_surface_material(VoxelMaterial material) noexcept; + void set_touch_type(VoxelTouch type) noexcept; + void set_touch_values(const glm::fvec3& values) noexcept; + void set_surface_material(VoxelMaterial material) noexcept; - VoxelBuilder& set_collision(const math::AABBf& box) noexcept; + void set_collision(const math::AABBf& box) noexcept; - VoxelBuilder& add_default_texture(std::string_view path); - VoxelBuilder& add_face_texture(VoxelFace face, std::string_view path); + void add_default_texture(std::string_view path); + void add_face_texture(VoxelFace face, std::string_view path); std::unique_ptr<Voxel> build(voxel_id id) const; }; diff --git a/game/shared/world/voxel_registry.cc b/game/shared/world/voxel_registry.cc index 97485e6..573a606 100644 --- a/game/shared/world/voxel_registry.cc +++ b/game/shared/world/voxel_registry.cc @@ -11,7 +11,7 @@ static void recalculate_checksum(void) registry_checksum = 0U;
for(const auto& voxel : world::voxel_registry::voxels) {
- registry_checksum = voxel->calculate_checksum(registry_checksum);
+ registry_checksum = voxel->get_checksum(registry_checksum);
}
}
@@ -39,7 +39,7 @@ world::Voxel* world::voxel_registry::find(std::string_view name) return nullptr;
}
- return voxels[it->second].get();
+ return voxels[it->second - 1].get();
}
world::Voxel* world::voxel_registry::find(voxel_id id)
|
