From 3bf42c6ff3805a0d42bbc661794a95ff31bedc26 Mon Sep 17 00:00:00 2001 From: untodesu Date: Sat, 15 Mar 2025 16:22:09 +0500 Subject: Add whatever I was working on for the last month --- game/shared/voxel_registry.cc | 184 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 game/shared/voxel_registry.cc (limited to 'game/shared/voxel_registry.cc') diff --git a/game/shared/voxel_registry.cc b/game/shared/voxel_registry.cc new file mode 100644 index 0000000..dea7179 --- /dev/null +++ b/game/shared/voxel_registry.cc @@ -0,0 +1,184 @@ +#include "shared/pch.hh" +#include "shared/voxel_registry.hh" + +#include "core/crc64.hh" + +std::unordered_map voxel_registry::builders = {}; +std::unordered_map voxel_registry::names = {}; +std::vector> voxel_registry::voxels = {}; + +VoxelInfoBuilder::VoxelInfoBuilder(const char *name, voxel_type type, bool animated, bool blending) +{ + prototype.name = name; + prototype.type = type; + prototype.animated = animated; + prototype.blending = blending; + + switch(type) { + case voxel_type::CUBE: + prototype.textures.resize(static_cast(voxel_face::CUBE__NR)); + break; + case voxel_type::CROSS: + prototype.textures.resize(static_cast(voxel_face::CROSS__NR)); + break; + case voxel_type::MODEL: + // Custom models should use a different texture + // resource management that is not a voxel atlas + // TODO: actually implement custom models lol + prototype.textures.resize(0); + break; + default: + // Something really bad should happen if we end up here. + // The outside code would static_cast an int to VoxelType + // and possibly fuck a lot of things up to cause this + spdlog::critical("voxel_registry: {}: unknown voxel type {}", name, static_cast(type)); + std::terminate(); + } + + // Physics properties + prototype.touch_type = voxel_touch::SOLID; + prototype.touch_values = glm::fvec3(0.0f, 0.0f, 0.0f); + prototype.surface = voxel_surface::DEFAULT; + + // Things set in future by item_def + prototype.item_pick = NULL_ITEM_ID; +} + +VoxelInfoBuilder &VoxelInfoBuilder::add_texture_default(const char *texture) +{ + default_texture.paths.push_back(texture); + return *this; +} + +VoxelInfoBuilder &VoxelInfoBuilder::add_texture(voxel_face face, const char *texture) +{ + const auto index = static_cast(face); + prototype.textures[index].paths.push_back(texture); + return *this; +} + +VoxelInfoBuilder &VoxelInfoBuilder::set_touch(voxel_touch type, const glm::fvec3 &values) +{ + prototype.touch_type = type; + prototype.touch_values = values; + return *this; +} + +VoxelInfoBuilder &VoxelInfoBuilder::set_surface(voxel_surface surface) +{ + prototype.surface = surface; + return *this; +} + +voxel_id VoxelInfoBuilder::build(void) const +{ + const auto it = voxel_registry::names.find(prototype.name); + + if(it != voxel_registry::names.cend()) { + spdlog::warn("voxel_registry: cannot build {}: name already present", prototype.name); + return it->second; + } + + std::size_t state_count; + + switch(prototype.type) { + case voxel_type::CUBE: + case voxel_type::CROSS: + case voxel_type::MODEL: + state_count = 1; + break; + default: + // Something really bad should happen if we end up here. + // The outside code would static_cast an int to VoxelType + // and possibly fuck a lot of things up to cause this + spdlog::critical("voxel_registry: {}: unknown voxel type {}", prototype.name, static_cast(prototype.type)); + std::terminate(); + } + + if((voxel_registry::voxels.size() + state_count) >= MAX_VOXEL_ID) { + spdlog::critical("voxel_registry: voxel registry overflow"); + std::terminate(); + } + + auto new_info = std::make_shared(); + new_info->name = prototype.name; + new_info->type = prototype.type; + new_info->animated = prototype.animated; + new_info->blending = prototype.blending; + + new_info->textures.resize(prototype.textures.size()); + + for(std::size_t i = 0; i < prototype.textures.size(); ++i) { + if(prototype.textures[i].paths.empty()) { + new_info->textures[i].paths = default_texture.paths; + new_info->textures[i].cached_offset = SIZE_MAX; + new_info->textures[i].cached_plane = SIZE_MAX; + } + else { + new_info->textures[i].paths = prototype.textures[i].paths; + new_info->textures[i].cached_offset = SIZE_MAX; + new_info->textures[i].cached_plane = SIZE_MAX; + } + } + + // Physics properties + new_info->touch_type = prototype.touch_type; + new_info->touch_values = prototype.touch_values; + new_info->surface = prototype.surface; + + // Things set in future by item_def + new_info->item_pick = prototype.item_pick; + + // Base voxel identifier offset + new_info->base_voxel = voxel_registry::voxels.size() + 1; + + for(std::size_t i = 0; i < state_count; ++i) + voxel_registry::voxels.push_back(new_info); + voxel_registry::names.insert_or_assign(new_info->name, new_info->base_voxel); + + return new_info->base_voxel; +} + +VoxelInfoBuilder &voxel_registry::construct(const char *name, voxel_type type, bool animated, bool blending) +{ + const auto it = voxel_registry::builders.find(name); + if(it != voxel_registry::builders.cend()) + return it->second; + return voxel_registry::builders.emplace(name, VoxelInfoBuilder(name, type, animated, blending)).first->second; +} + +VoxelInfo *voxel_registry::find(const char *name) +{ + const auto it = voxel_registry::names.find(name); + if(it != voxel_registry::names.cend()) + return voxel_registry::find(it->second); + return nullptr; +} + +VoxelInfo *voxel_registry::find(const voxel_id voxel) +{ + if((voxel != NULL_VOXEL_ID) && (voxel <= voxel_registry::voxels.size())) + return voxel_registry::voxels[voxel - 1].get(); + return nullptr; +} + +void voxel_registry::purge(void) +{ + voxel_registry::builders.clear(); + voxel_registry::names.clear(); + voxel_registry::voxels.clear(); +} + +std::uint64_t voxel_registry::checksum(void) +{ + std::uint64_t result = 0; + + for(const std::shared_ptr &info : voxel_registry::voxels) { + result = crc64::get(info->name, result); + result += static_cast(info->type); + result += static_cast(info->base_voxel); + result += info->blending ? 256 : 1; + } + + return result; +} -- cgit