diff options
Diffstat (limited to 'game/client')
| -rw-r--r-- | game/client/experiments.cc | 13 | ||||
| -rw-r--r-- | game/client/game.cc | 40 | ||||
| -rw-r--r-- | game/client/gui/bother.cc | 8 | ||||
| -rw-r--r-- | game/client/gui/bother.hh | 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/play_menu.cc | 92 | ||||
| -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/gui/window_title.cc | 11 | ||||
| -rw-r--r-- | game/client/io/glfw.hh | 4 | ||||
| -rw-r--r-- | game/client/session.cc | 18 | ||||
| -rw-r--r-- | game/client/world/chunk_mesher.cc | 192 | ||||
| -rw-r--r-- | game/client/world/chunk_quad.hh | 6 | ||||
| -rw-r--r-- | game/client/world/player_target.cc | 15 | ||||
| -rw-r--r-- | game/client/world/player_target.hh | 3 | ||||
| -rw-r--r-- | game/client/world/voxel_sounds.cc | 53 | ||||
| -rw-r--r-- | game/client/world/voxel_sounds.hh | 6 |
18 files changed, 253 insertions, 246 deletions
diff --git a/game/client/experiments.cc b/game/client/experiments.cc index 2b9fe89..8b0b526 100644 --- a/game/client/experiments.cc +++ b/game/client/experiments.cc @@ -22,7 +22,7 @@ static void on_glfw_mouse_button(const io::GlfwMouseButtonEvent& event)
{
if(!globals::gui_screen && session::is_ingame()) {
- if((event.action == GLFW_PRESS) && (world::player_target::voxel != NULL_VOXEL_ID)) {
+ if((event.action == GLFW_PRESS) && world::player_target::voxel) {
if(event.button == GLFW_MOUSE_BUTTON_LEFT) {
experiments::attack();
return;
@@ -68,14 +68,17 @@ void experiments::update_late(void) void experiments::attack(void)
{
- globals::dimension->set_voxel(NULL_VOXEL_ID, world::player_target::coord);
+ globals::dimension->set_voxel(nullptr, world::player_target::coord);
}
void experiments::interact(void)
{
- if(auto info = world::item_registry::find(gui::hotbar::slots[gui::hotbar::active_slot])) {
- if(info->place_voxel != NULL_VOXEL_ID) {
- 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 a59aec3..d61ce84 100644 --- a/game/client/game.cc +++ b/game/client/game.cc @@ -372,32 +372,48 @@ void client_game::init_late(void) // NOTE: this is very debug, early and a quite
// conservative limit choice; there must be a better
// way to make this limit way smaller than it currently is
- for(const std::shared_ptr<world::VoxelInfo>& info : world::voxel_registry::voxels) {
- for(const world::VoxelTexture& vtex : info->textures) {
- max_texture_count += vtex.paths.size();
- }
+ for(const auto& voxel : world::voxel_registry::voxels) {
+ max_texture_count += voxel->get_default_textures().size();
+ max_texture_count += voxel->get_face_textures(world::VFACE_NORTH).size();
+ max_texture_count += voxel->get_face_textures(world::VFACE_SOUTH).size();
+ max_texture_count += voxel->get_face_textures(world::VFACE_EAST).size();
+ max_texture_count += voxel->get_face_textures(world::VFACE_WEST).size();
+ max_texture_count += voxel->get_face_textures(world::VFACE_TOP).size();
+ max_texture_count += voxel->get_face_textures(world::VFACE_BOTTOM).size();
+ max_texture_count += voxel->get_face_textures(world::VFACE_CROSS_NWSE).size();
+ max_texture_count += voxel->get_face_textures(world::VFACE_CROSS_NESW).size();
}
// UNDONE: asset packs for non-16x16 stuff
world::voxel_atlas::create(16, 16, max_texture_count);
- for(std::shared_ptr<world::VoxelInfo>& info : world::voxel_registry::voxels) {
- for(world::VoxelTexture& vtex : info->textures) {
- if(auto strip = world::voxel_atlas::find_or_load(vtex.paths)) {
- vtex.cached_offset = strip->offset;
- vtex.cached_plane = strip->plane;
+ for(auto& voxel : world::voxel_registry::voxels) {
+ constexpr std::array faces = {
+ world::VFACE_NORTH,
+ world::VFACE_SOUTH,
+ world::VFACE_EAST,
+ world::VFACE_WEST,
+ world::VFACE_TOP,
+ world::VFACE_BOTTOM,
+ world::VFACE_CROSS_NWSE,
+ world::VFACE_CROSS_NESW,
+ };
+
+ for(auto face : faces) {
+ if(auto strip = world::voxel_atlas::find_or_load(voxel->get_face_textures(face))) {
+ voxel->set_face_cache(face, strip->offset, strip->plane);
continue;
}
- spdlog::critical("client_gl: {}: failed to load atlas strips", info->name);
+ spdlog::critical("client_gl: {}: failed to load atlas strips", voxel->get_name());
std::terminate();
}
}
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/bother.cc b/game/client/gui/bother.cc index 1bb7097..e87b9ff 100644 --- a/game/client/gui/bother.cc +++ b/game/client/gui/bother.cc @@ -2,6 +2,8 @@ #include "client/gui/bother.hh"
+#include "core/version.hh"
+
#include "shared/protocol.hh"
#include "client/globals.hh"
@@ -29,10 +31,12 @@ static void on_status_response_packet(const protocol::StatusResponse& packet) gui::BotherResponseEvent event;
event.identity = identity;
event.is_server_unreachable = false;
- event.protocol_version = packet.version;
event.num_players = packet.num_players;
event.max_players = packet.max_players;
event.motd = packet.motd;
+ event.game_version_major = packet.game_version_major;
+ event.game_version_minor = packet.game_version_minor;
+ event.game_version_patch = packet.game_version_patch;
globals::dispatcher.trigger(event);
enet_peer_disconnect(packet.peer, protocol::CHANNEL);
@@ -89,7 +93,7 @@ void gui::bother::update_late(void) if(0 < enet_host_service(bother_host, &enet_event, 0)) {
if(enet_event.type == ENET_EVENT_TYPE_CONNECT) {
protocol::StatusRequest packet;
- packet.version = protocol::VERSION;
+ packet.game_version_major = version::major;
protocol::send(enet_event.peer, protocol::encode(packet));
return;
}
diff --git a/game/client/gui/bother.hh b/game/client/gui/bother.hh index fc5bab4..75e56d1 100644 --- a/game/client/gui/bother.hh +++ b/game/client/gui/bother.hh @@ -5,9 +5,11 @@ namespace gui struct BotherResponseEvent final {
unsigned int identity;
bool is_server_unreachable;
- std::uint32_t protocol_version;
std::uint16_t num_players;
std::uint16_t max_players;
+ std::uint32_t game_version_major;
+ std::uint32_t game_version_minor;
+ std::uint32_t game_version_patch;
std::string motd;
};
} // namespace gui
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/play_menu.cc b/game/client/gui/play_menu.cc index 5b9887e..ad85141 100644 --- a/game/client/gui/play_menu.cc +++ b/game/client/gui/play_menu.cc @@ -10,6 +10,8 @@ #include "core/utils/string.hh"
+#include "core/version.hh"
+
#include "shared/protocol.hh"
#include "client/gui/bother.hh"
@@ -25,9 +27,8 @@ constexpr static ImGuiWindowFlags WINDOW_FLAGS = ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration;
constexpr static std::string_view DEFAULT_SERVER_NAME = "Voxelius Server";
constexpr static std::string_view SERVERS_TXT = "servers.txt";
-constexpr static std::string_view WARNING_TOAST = "[!]";
-constexpr static std::size_t MAX_SERVER_ITEM_NAME = 24;
+constexpr static std::size_t MAX_SERVER_ITEM_NAME = 18;
enum class item_status : unsigned int {
UNKNOWN = 0x0000U,
@@ -43,10 +44,12 @@ struct ServerStatusItem final { std::uint16_t port;
// Things pulled from bother events
- std::uint32_t protocol_version;
std::uint16_t num_players;
std::uint16_t max_players;
std::string motd;
+ std::uint16_t game_version_major;
+ std::uint16_t game_version_minor;
+ std::uint16_t game_version_patch;
// Unique identifier that monotonically
// grows with each new server added and
@@ -69,9 +72,6 @@ static std::string str_status_init; static std::string str_status_ping;
static std::string str_status_fail;
-static std::string str_outdated_client;
-static std::string str_outdated_server;
-
static std::string input_itemname;
static std::string input_hostname;
static std::string input_password;
@@ -106,11 +106,13 @@ static void add_new_server(void) {
auto item = new ServerStatusItem();
item->port = protocol::PORT;
- item->protocol_version = protocol::VERSION;
item->max_players = UINT16_MAX;
item->num_players = UINT16_MAX;
item->identity = next_identity;
item->status = item_status::UNKNOWN;
+ item->game_version_major = 0U;
+ item->game_version_minor = 0U;
+ item->game_version_patch = 0U;
next_identity += 1U;
@@ -202,9 +204,6 @@ static void on_language_set(const gui::LanguageSetEvent& event) str_status_init = gui::language::resolve("play_menu.status.init");
str_status_ping = gui::language::resolve("play_menu.status.ping");
str_status_fail = gui::language::resolve("play_menu.status.fail");
-
- str_outdated_client = gui::language::resolve("play_menu.outdated_client");
- str_outdated_server = gui::language::resolve("play_menu.outdated_server");
}
static void on_bother_response(const gui::BotherResponseEvent& event)
@@ -212,18 +211,22 @@ static void on_bother_response(const gui::BotherResponseEvent& event) for(auto item : servers_deque) {
if(item->identity == event.identity) {
if(event.is_server_unreachable) {
- item->protocol_version = 0U;
item->num_players = UINT16_MAX;
item->max_players = UINT16_MAX;
item->motd = str_status_fail;
item->status = item_status::FAILURE;
+ item->game_version_major = 0U;
+ item->game_version_minor = 0U;
+ item->game_version_patch = 0U;
}
else {
- item->protocol_version = event.protocol_version;
item->num_players = event.num_players;
item->max_players = event.max_players;
item->motd = event.motd;
item->status = item_status::REACHED;
+ item->game_version_major = event.game_version_major;
+ item->game_version_minor = event.game_version_minor;
+ item->game_version_patch = event.game_version_patch;
}
break;
@@ -264,30 +267,50 @@ static void layout_server_item(ServerStatusItem* item) if(item->status == item_status::REACHED) {
auto stats = std::format("{}/{}", item->num_players, item->max_players);
- auto stats_width = ImGui::CalcTextSize(stats.c_str(), stats.c_str() + stats.size()).x;
- auto stats_pos = ImVec2(cursor.x + item_width - stats_width - padding.x, cursor.y + padding.y);
+ auto stats_size = ImGui::CalcTextSize(stats.c_str(), stats.c_str() + stats.size());
+ auto stats_pos = ImVec2(cursor.x + item_width - stats_size.x - padding.x, cursor.y + padding.y);
draw_list->AddText(stats_pos, ImGui::GetColorU32(ImGuiCol_TextDisabled), stats.c_str(), stats.c_str() + stats.size());
- if(item->protocol_version != protocol::VERSION) {
- auto warning_size = ImGui::CalcTextSize(WARNING_TOAST.data(), WARNING_TOAST.data() + WARNING_TOAST.size());
- auto warning_pos = ImVec2(stats_pos.x - warning_size.x - padding.x - 4.0f * globals::gui_scale, cursor.y + padding.y);
- auto warning_end = ImVec2(warning_pos.x + warning_size.x, warning_pos.y + warning_size.y);
- draw_list->AddText(warning_pos, ImGui::GetColorU32(ImGuiCol_DragDropTarget), WARNING_TOAST.data(),
- WARNING_TOAST.data() + WARNING_TOAST.size());
+ auto major_version_mismatch = item->game_version_major != version::major;
+ auto minor_version_mismatch = item->game_version_minor != version::minor;
+ auto patch_version_mismatch = item->game_version_patch != version::patch;
- if(ImGui::IsMouseHoveringRect(warning_pos, warning_end)) {
- ImGui::BeginTooltip();
+ ImU32 version_color;
- if(item->protocol_version < protocol::VERSION) {
- ImGui::TextUnformatted(str_outdated_server.c_str(), str_outdated_server.c_str() + str_outdated_server.size());
- }
- else {
- ImGui::TextUnformatted(str_outdated_client.c_str(), str_outdated_client.c_str() + str_outdated_client.size());
- }
+ if(major_version_mismatch || minor_version_mismatch || patch_version_mismatch) {
+ version_color = ImGui::GetColorU32(major_version_mismatch ? ImGuiCol_PlotLinesHovered : ImGuiCol_DragDropTarget);
+ }
+ else {
+ version_color = ImGui::GetColorU32(ImGuiCol_PlotHistogram);
+ }
- ImGui::EndTooltip();
- }
+ ImGui::PushFont(globals::font_unscii8, 4.0f);
+
+ std::string version_toast;
+
+ if(item->game_version_major < 16U) {
+ // Pre v16.x.x servers didn't send minor and patch versions
+ // and also used a different versioning scheme; post v16 the
+ // major version became the protocol version and the semver lost the tweak part
+ version_toast = std::string("0.0.1");
+ }
+ else {
+ version_toast = std::format("{}.{}.{}", item->game_version_major, item->game_version_minor, item->game_version_patch);
}
+
+ auto version_size = ImGui::CalcTextSize(version_toast.c_str(), version_toast.c_str() + version_toast.size());
+ auto version_pos = ImVec2(stats_pos.x - version_size.x - padding.x - 4.0f * globals::gui_scale,
+ cursor.y + padding.y + 0.5f * (stats_size.y - version_size.y));
+ auto version_end = ImVec2(version_pos.x + version_size.x, version_pos.y + version_size.y);
+
+ auto outline_pos = ImVec2(version_pos.x - 2U * globals::gui_scale, version_pos.y - 2U * globals::gui_scale);
+ auto outline_end = ImVec2(version_end.x + 2U * globals::gui_scale, version_end.y + 2U * globals::gui_scale);
+ auto outline_thickness = math::max<float>(1.0f, 0.5f * static_cast<float>(globals::gui_scale));
+
+ draw_list->AddRect(outline_pos, outline_end, version_color, 0.0f, 0, outline_thickness);
+ draw_list->AddText(version_pos, version_color, version_toast.c_str(), version_toast.c_str() + version_toast.size());
+
+ ImGui::PopFont();
}
ImU32 motd_color = {};
@@ -460,11 +483,13 @@ void gui::play_menu::init(void) auto item = new ServerStatusItem();
item->port = protocol::PORT;
- item->protocol_version = protocol::VERSION;
item->max_players = UINT16_MAX;
item->num_players = UINT16_MAX;
item->identity = next_identity;
item->status = item_status::UNKNOWN;
+ item->game_version_major = version::major;
+ item->game_version_minor = version::minor;
+ item->game_version_patch = version::patch;
next_identity += 1U;
@@ -543,6 +568,11 @@ void gui::play_menu::layout(void) ImGui::EndTabItem();
}
+ if(ImGui::BeginTabItem("debug###play_menu.debug.child")) {
+ ImGui::ShowStyleEditor();
+ ImGui::EndTabItem();
+ }
+
ImGui::EndTabBar();
}
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/gui/window_title.cc b/game/client/gui/window_title.cc index 6e2387c..2f96205 100644 --- a/game/client/gui/window_title.cc +++ b/game/client/gui/window_title.cc @@ -10,14 +10,5 @@ void gui::window_title::update(void)
{
- std::string title;
-
- if(globals::sound_ctx && globals::sound_dev) {
- title = std::format("Voxelius {}: {}", version::semver, splash::get());
- }
- else {
- title = std::format("Voxelius {}: {} [NOSOUND]", version::semver, splash::get());
- }
-
- glfwSetWindowTitle(globals::window, title.c_str());
+ glfwSetWindowTitle(globals::window, std::format("Voxelius {}: {}", version::semver, splash::get()).c_str());
}
diff --git a/game/client/io/glfw.hh b/game/client/io/glfw.hh index bbd767a..7697d97 100644 --- a/game/client/io/glfw.hh +++ b/game/client/io/glfw.hh @@ -1,5 +1,3 @@ -#ifndef CLIENTFW
-#define CLIENTFW 1
#pragma once
namespace io
@@ -36,5 +34,3 @@ struct GlfwScrollEvent final { float dy;
};
} // namespace io
-
-#endif // CLIENTFW
diff --git a/game/client/session.cc b/game/client/session.cc index 7e0d36c..ce3d616 100644 --- a/game/client/session.cc +++ b/game/client/session.cc @@ -6,6 +6,8 @@ #include "core/math/crc64.hh"
+#include "core/version.hh"
+
#include "shared/entity/head.hh"
#include "shared/entity/player.hh"
#include "shared/entity/transform.hh"
@@ -98,8 +100,10 @@ static void on_set_voxel_packet(const protocol::SetVoxel& packet) auto index = coord::to_index(lpos);
if(auto chunk = globals::dimension->find_chunk(cpos)) {
- if(chunk->get_voxel(index) != packet.voxel) {
- chunk->set_voxel(packet.voxel, index);
+ auto packet_voxel = world::voxel_registry::find(packet.voxel);
+
+ if(chunk->get_voxel(index) != packet_voxel) {
+ chunk->set_voxel(packet_voxel, index);
world::ChunkUpdateEvent event;
event.dimension = globals::dimension;
@@ -125,7 +129,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;
+ packet.voxel = event.voxel ? event.voxel->get_id() : NULL_VOXEL_ID;
protocol::send(session::peer, protocol::encode(packet));
}
@@ -282,11 +286,13 @@ void session::disconnect(std::string_view reason) void session::send_login_request(void)
{
protocol::LoginRequest packet;
- packet.version = protocol::VERSION;
- packet.voxel_registry_checksum = world::voxel_registry::calculate_checksum();
- packet.item_registry_checksum = world::item_registry::calculate_checksum();
+ packet.game_version_major = version::major;
+ packet.voxel_registry_checksum = world::voxel_registry::get_checksum();
+ packet.item_registry_checksum = world::item_registry::get_checksum();
packet.password_hash = server_password_hash;
packet.username = client_game::username.get();
+ packet.game_version_minor = version::minor;
+ packet.game_version_patch = version::patch;
protocol::send(session::peer, protocol::encode(packet));
diff --git a/game/client/world/chunk_mesher.cc b/game/client/world/chunk_mesher.cc index a8ee817..bc90a03 100644 --- a/game/client/world/chunk_mesher.cc +++ b/game/client/world/chunk_mesher.cc @@ -8,6 +8,7 @@ #include "shared/world/chunk.hh"
#include "shared/world/dimension.hh"
+#include "shared/world/voxel.hh"
#include "shared/world/voxel_registry.hh"
#include "shared/coord.hh"
@@ -56,37 +57,6 @@ static const CachedChunkCoord get_cached_cpos(const chunk_pos& pivot, const chun return CPOS_ITSELF;
}
-static world::voxel_facing get_facing(world::voxel_face face, world::voxel_type type)
-{
- if(type == world::voxel_type::CROSS) {
- switch(face) {
- case world::voxel_face::CROSS_NESW:
- return world::voxel_facing::NESW;
- case world::voxel_face::CROSS_NWSE:
- return world::voxel_facing::NWSE;
- default:
- return world::voxel_facing::NORTH;
- }
- }
-
- switch(face) {
- case world::voxel_face::CUBE_NORTH:
- return world::voxel_facing::NORTH;
- case world::voxel_face::CUBE_SOUTH:
- return world::voxel_facing::SOUTH;
- case world::voxel_face::CUBE_EAST:
- return world::voxel_facing::EAST;
- case world::voxel_face::CUBE_WEST:
- return world::voxel_facing::WEST;
- case world::voxel_face::CUBE_TOP:
- return world::voxel_facing::UP;
- case world::voxel_face::CUBE_BOTTOM:
- return world::voxel_facing::DOWN;
- default:
- return world::voxel_facing::NORTH;
- }
-}
-
class GL_MeshingTask final : public Task {
public:
explicit GL_MeshingTask(entt::entity entity, const chunk_pos& cpos);
@@ -95,11 +65,10 @@ public: virtual void finalize(void) override;
private:
- bool vis_test(voxel_id voxel, const world::VoxelInfo* info, const local_pos& lpos) const;
- void push_quad_a(const world::VoxelInfo* info, const glm::fvec3& pos, const glm::fvec2& size, world::voxel_face face);
- void push_quad_v(const world::VoxelInfo* info, const glm::fvec3& pos, const glm::fvec2& size, world::voxel_face face,
- std::size_t entropy);
- void make_cube(voxel_id voxel, const world::VoxelInfo* info, const local_pos& lpos, world::voxel_vis vis, std::size_t entropy);
+ bool vis_test(const world::Voxel* voxel, const local_pos& lpos) const;
+ void push_quad_a(const world::Voxel* voxel, const glm::fvec3& pos, const glm::fvec2& size, world::VoxelFace face);
+ void push_quad_v(const world::Voxel* voxel, const glm::fvec3& pos, const glm::fvec2& size, world::VoxelFace face, std::size_t entropy);
+ void make_cube(const world::Voxel* voxel, const local_pos& lpos, world::VoxelVisBits vis, std::size_t entropy);
void cache_chunk(const chunk_pos& cpos);
private:
@@ -138,41 +107,39 @@ void GL_MeshingTask::process(void) return;
}
- const auto voxel = voxels[i];
const auto lpos = coord::to_local(i);
+ const auto voxel = world::voxel_registry::find(voxels[i]);
- const auto info = world::voxel_registry::find(voxel);
-
- if(info == nullptr) {
+ if(voxel == nullptr) {
// Either a NULL_VOXEL_ID or something went
// horribly wrong and we don't what this is
continue;
}
- world::voxel_vis vis = 0;
+ unsigned int vis = 0U;
- if(vis_test(voxel, info, lpos + DIR_NORTH<local_pos::value_type>)) {
- vis |= world::VIS_NORTH;
+ if(vis_test(voxel, lpos + DIR_NORTH<local_pos::value_type>)) {
+ vis |= world::VVIS_NORTH;
}
- if(vis_test(voxel, info, lpos + DIR_SOUTH<local_pos::value_type>)) {
- vis |= world::VIS_SOUTH;
+ if(vis_test(voxel, lpos + DIR_SOUTH<local_pos::value_type>)) {
+ vis |= world::VVIS_SOUTH;
}
- if(vis_test(voxel, info, lpos + DIR_EAST<local_pos::value_type>)) {
- vis |= world::VIS_EAST;
+ if(vis_test(voxel, lpos + DIR_EAST<local_pos::value_type>)) {
+ vis |= world::VVIS_EAST;
}
- if(vis_test(voxel, info, lpos + DIR_WEST<local_pos::value_type>)) {
- vis |= world::VIS_WEST;
+ if(vis_test(voxel, lpos + DIR_WEST<local_pos::value_type>)) {
+ vis |= world::VVIS_WEST;
}
- if(vis_test(voxel, info, lpos + DIR_UP<local_pos::value_type>)) {
- vis |= world::VIS_UP;
+ if(vis_test(voxel, lpos + DIR_UP<local_pos::value_type>)) {
+ vis |= world::VVIS_UP;
}
- if(vis_test(voxel, info, lpos + DIR_DOWN<local_pos::value_type>)) {
- vis |= world::VIS_DOWN;
+ if(vis_test(voxel, lpos + DIR_DOWN<local_pos::value_type>)) {
+ vis |= world::VVIS_DOWN;
}
const auto vpos = coord::to_voxel(m_cpos, lpos);
@@ -180,7 +147,7 @@ void GL_MeshingTask::process(void) const auto entropy = math::crc64(&entropy_src, sizeof(entropy_src));
// FIXME: handle different voxel types
- make_cube(voxel, info, lpos, vis, entropy);
+ make_cube(voxel, lpos, world::VoxelVisBits(vis), entropy);
}
}
@@ -254,7 +221,7 @@ void GL_MeshingTask::finalize(void) }
}
-bool GL_MeshingTask::vis_test(voxel_id voxel, const world::VoxelInfo* info, const local_pos& lpos) const
+bool GL_MeshingTask::vis_test(const world::Voxel* voxel, const local_pos& lpos) const
{
const auto pvpos = coord::to_voxel(m_cpos, lpos);
const auto pcpos = coord::to_chunk(pvpos);
@@ -263,26 +230,18 @@ bool GL_MeshingTask::vis_test(voxel_id voxel, const world::VoxelInfo* info, cons const auto cached_cpos = get_cached_cpos(m_cpos, pcpos);
const auto& voxels = m_cache.at(cached_cpos);
- const auto neighbour = voxels[index];
+ const auto neighbour = world::voxel_registry::find(voxels[index]);
bool result;
- if(neighbour == NULL_VOXEL_ID) {
+ if(neighbour == nullptr) {
result = true;
}
else if(neighbour == voxel) {
result = false;
}
- else if(auto neighbour_info = world::voxel_registry::find(neighbour)) {
- if(neighbour_info->blending != info->blending) {
- // Voxel types that use blending are semi-transparent;
- // this means they're rendered using a different setup
- // and they must have visible faces with opaque voxels
- result = neighbour_info->blending;
- }
- else {
- result = false;
- }
+ else if(neighbour->get_render_mode() != voxel->get_render_mode()) {
+ result = true;
}
else {
result = false;
@@ -291,88 +250,95 @@ bool GL_MeshingTask::vis_test(voxel_id voxel, const world::VoxelInfo* info, cons return result;
}
-void GL_MeshingTask::push_quad_a(const world::VoxelInfo* info, const glm::fvec3& pos, const glm::fvec2& size, world::voxel_face face)
+void GL_MeshingTask::push_quad_a(const world::Voxel* voxel, const glm::fvec3& pos, const glm::fvec2& size, world::VoxelFace face)
{
- const world::voxel_facing facing = get_facing(face, info->type);
- const world::VoxelTexture& vtex = info->textures[static_cast<std::size_t>(face)];
-
- if(info->blending) {
- m_quads_b[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset, vtex.paths.size()));
- }
- else {
- m_quads_s[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset, vtex.paths.size()));
+ auto cached_offset = voxel->get_cached_face_offset(face);
+ auto cached_plane = voxel->get_cached_face_plane(face);
+ auto& textures = voxel->get_face_textures(face);
+
+ switch(voxel->get_render_mode()) {
+ case world::VRENDER_OPAQUE:
+ m_quads_s[cached_plane].push_back(make_chunk_quad(pos, size, face, cached_offset, textures.size()));
+ break;
+
+ case world::VRENDER_BLEND:
+ m_quads_b[cached_plane].push_back(make_chunk_quad(pos, size, face, cached_offset, textures.size()));
+ break;
}
}
-void GL_MeshingTask::push_quad_v(const world::VoxelInfo* info, const glm::fvec3& pos, const glm::fvec2& size, world::voxel_face face,
+void GL_MeshingTask::push_quad_v(const world::Voxel* voxel, const glm::fvec3& pos, const glm::fvec2& size, world::VoxelFace face,
std::size_t entropy)
{
- const world::voxel_facing facing = get_facing(face, info->type);
- const world::VoxelTexture& vtex = info->textures[static_cast<std::size_t>(face)];
- const std::size_t entropy_mod = entropy % vtex.paths.size();
-
- if(info->blending) {
- m_quads_b[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset + entropy_mod, 0));
- }
- else {
- m_quads_s[vtex.cached_plane].push_back(make_chunk_quad(pos, size, facing, vtex.cached_offset + entropy_mod, 0));
+ auto cached_offset = voxel->get_cached_face_offset(face);
+ auto cached_plane = voxel->get_cached_face_plane(face);
+ auto& textures = voxel->get_face_textures(face);
+ auto index = entropy % textures.size();
+
+ switch(voxel->get_render_mode()) {
+ case world::VRENDER_OPAQUE:
+ m_quads_s[cached_plane].push_back(make_chunk_quad(pos, size, face, cached_offset + index, 0));
+ break;
+
+ case world::VRENDER_BLEND:
+ m_quads_b[cached_plane].push_back(make_chunk_quad(pos, size, face, cached_offset + index, 0));
+ break;
}
}
-void GL_MeshingTask::make_cube(voxel_id voxel, const world::VoxelInfo* info, const local_pos& lpos, world::voxel_vis vis,
- std::size_t entropy)
+void GL_MeshingTask::make_cube(const world::Voxel* voxel, const local_pos& lpos, world::VoxelVisBits vis, std::size_t entropy)
{
const glm::fvec3 fpos = glm::fvec3(lpos);
const glm::fvec2 fsize = glm::fvec2(1.0f, 1.0f);
- if(info->animated) {
- if(vis & world::VIS_NORTH) {
- push_quad_a(info, fpos, fsize, world::voxel_face::CUBE_NORTH);
+ if(voxel->is_animated()) {
+ if(vis & world::VVIS_NORTH) {
+ push_quad_a(voxel, fpos, fsize, world::VFACE_NORTH);
}
- if(vis & world::VIS_SOUTH) {
- push_quad_a(info, fpos, fsize, world::voxel_face::CUBE_SOUTH);
+ if(vis & world::VVIS_SOUTH) {
+ push_quad_a(voxel, fpos, fsize, world::VFACE_SOUTH);
}
- if(vis & world::VIS_EAST) {
- push_quad_a(info, fpos, fsize, world::voxel_face::CUBE_EAST);
+ if(vis & world::VVIS_EAST) {
+ push_quad_a(voxel, fpos, fsize, world::VFACE_EAST);
}
- if(vis & world::VIS_WEST) {
- push_quad_a(info, fpos, fsize, world::voxel_face::CUBE_WEST);
+ if(vis & world::VVIS_WEST) {
+ push_quad_a(voxel, fpos, fsize, world::VFACE_WEST);
}
- if(vis & world::VIS_UP) {
- push_quad_a(info, fpos, fsize, world::voxel_face::CUBE_TOP);
+ if(vis & world::VVIS_UP) {
+ push_quad_a(voxel, fpos, fsize, world::VFACE_TOP);
}
- if(vis & world::VIS_DOWN) {
- push_quad_a(info, fpos, fsize, world::voxel_face::CUBE_BOTTOM);
+ if(vis & world::VVIS_DOWN) {
+ push_quad_a(voxel, fpos, fsize, world::VFACE_BOTTOM);
}
}
else {
- if(vis & world::VIS_NORTH) {
- push_quad_v(info, fpos, fsize, world::voxel_face::CUBE_NORTH, entropy);
+ if(vis & world::VVIS_NORTH) {
+ push_quad_v(voxel, fpos, fsize, world::VFACE_NORTH, entropy);
}
- if(vis & world::VIS_SOUTH) {
- push_quad_v(info, fpos, fsize, world::voxel_face::CUBE_SOUTH, entropy);
+ if(vis & world::VVIS_SOUTH) {
+ push_quad_v(voxel, fpos, fsize, world::VFACE_SOUTH, entropy);
}
- if(vis & world::VIS_EAST) {
- push_quad_v(info, fpos, fsize, world::voxel_face::CUBE_EAST, entropy);
+ if(vis & world::VVIS_EAST) {
+ push_quad_v(voxel, fpos, fsize, world::VFACE_EAST, entropy);
}
- if(vis & world::VIS_WEST) {
- push_quad_v(info, fpos, fsize, world::voxel_face::CUBE_WEST, entropy);
+ if(vis & world::VVIS_WEST) {
+ push_quad_v(voxel, fpos, fsize, world::VFACE_WEST, entropy);
}
- if(vis & world::VIS_UP) {
- push_quad_v(info, fpos, fsize, world::voxel_face::CUBE_TOP, entropy);
+ if(vis & world::VVIS_UP) {
+ push_quad_v(voxel, fpos, fsize, world::VFACE_TOP, entropy);
}
- if(vis & world::VIS_DOWN) {
- push_quad_v(info, fpos, fsize, world::voxel_face::CUBE_BOTTOM, entropy);
+ if(vis & world::VVIS_DOWN) {
+ push_quad_v(voxel, fpos, fsize, world::VFACE_BOTTOM, entropy);
}
}
}
diff --git a/game/client/world/chunk_quad.hh b/game/client/world/chunk_quad.hh index c15bb7a..d68977e 100644 --- a/game/client/world/chunk_quad.hh +++ b/game/client/world/chunk_quad.hh @@ -13,8 +13,8 @@ using ChunkQuad = std::array<std::uint32_t, 2>; namespace world
{
-constexpr inline static ChunkQuad make_chunk_quad(const glm::fvec3& position, const glm::fvec2& size, voxel_facing facing,
- std::size_t texture, std::size_t frames)
+constexpr inline static ChunkQuad make_chunk_quad(const glm::fvec3& position, const glm::fvec2& size, VoxelFace face, std::size_t texture,
+ std::size_t frames)
{
ChunkQuad result = {};
result[0] = 0x00000000;
@@ -30,7 +30,7 @@ constexpr inline static ChunkQuad make_chunk_quad(const glm::fvec3& position, co result[0] |= (0x0000000FU & static_cast<std::uint32_t>(size.y * 16.0f - 1.0f));
// [1] FFFF----------------------------
- result[1] |= (0x0000000FU & static_cast<std::uint32_t>(facing)) << 28U;
+ result[1] |= (0x0000000FU & static_cast<std::uint32_t>(face)) << 28U;
// [1] ----TTTTTTTTTTTAAAAA------------
result[1] |= (0x000007FFU & static_cast<std::uint32_t>(texture)) << 17U;
diff --git a/game/client/world/player_target.cc b/game/client/world/player_target.cc index f0550c0..3ede47e 100644 --- a/game/client/world/player_target.cc +++ b/game/client/world/player_target.cc @@ -16,17 +16,15 @@ constexpr static float MAX_REACH = 16.0f;
-voxel_id world::player_target::voxel;
voxel_pos world::player_target::coord;
voxel_pos world::player_target::normal;
-const world::VoxelInfo* world::player_target::info;
+const world::Voxel* world::player_target::voxel;
void world::player_target::init(void)
{
- world::player_target::voxel = NULL_VOXEL_ID;
world::player_target::coord = voxel_pos();
world::player_target::normal = voxel_pos();
- world::player_target::info = nullptr;
+ world::player_target::voxel = nullptr;
}
void world::player_target::update(void)
@@ -37,29 +35,26 @@ void world::player_target::update(void) do {
world::player_target::voxel = ray.step();
- if(world::player_target::voxel != NULL_VOXEL_ID) {
+ if(world::player_target::voxel) {
world::player_target::coord = ray.vpos;
world::player_target::normal = ray.vnormal;
- world::player_target::info = world::voxel_registry::find(world::player_target::voxel);
break;
}
world::player_target::coord = voxel_pos();
world::player_target::normal = voxel_pos();
- world::player_target::info = nullptr;
} while(ray.distance < MAX_REACH);
}
else {
- world::player_target::voxel = NULL_VOXEL_ID;
+ world::player_target::voxel = nullptr;
world::player_target::coord = voxel_pos();
world::player_target::normal = voxel_pos();
- world::player_target::info = nullptr;
}
}
void world::player_target::render(void)
{
- if((world::player_target::voxel != NULL_VOXEL_ID) && !client_game::hide_hud) {
+ if(world::player_target::voxel && !client_game::hide_hud) {
auto cpos = coord::to_chunk(world::player_target::coord);
auto fpos = coord::to_local(world::player_target::coord);
diff --git a/game/client/world/player_target.hh b/game/client/world/player_target.hh index f0db9be..34532c3 100644 --- a/game/client/world/player_target.hh +++ b/game/client/world/player_target.hh @@ -4,10 +4,9 @@ namespace world::player_target
{
-extern voxel_id voxel;
extern voxel_pos coord;
extern voxel_pos normal;
-extern const VoxelInfo* info;
+extern const Voxel* voxel;
} // namespace world::player_target
namespace world::player_target
diff --git a/game/client/world/voxel_sounds.cc b/game/client/world/voxel_sounds.cc index 481e615..fe91f01 100644 --- a/game/client/world/voxel_sounds.cc +++ b/game/client/world/voxel_sounds.cc @@ -4,24 +4,21 @@ #include "client/resource/sound_effect.hh"
-constexpr static std::size_t NUM_SURFACES = static_cast<std::size_t>(world::voxel_surface::COUNT);
-
-static std::vector<resource_ptr<SoundEffect>> footsteps_sounds[NUM_SURFACES];
+static std::vector<resource_ptr<SoundEffect>> footsteps_sounds[world::VMAT_COUNT];
static std::mt19937_64 randomizer;
-static void add_footsteps_effect(world::voxel_surface surface, std::string_view name)
+static void add_footsteps_effect(world::VoxelMaterial material, std::string_view name)
{
if(auto effect = resource::load<SoundEffect>(name)) {
- auto surface_index = static_cast<std::size_t>(surface);
- footsteps_sounds[surface_index].push_back(effect);
+ footsteps_sounds[material].push_back(effect);
}
}
-static resource_ptr<SoundEffect> get_footsteps_effect(world::voxel_surface surface)
+static resource_ptr<SoundEffect> get_footsteps_effect(world::VoxelMaterial material)
{
- auto surface_index = static_cast<std::size_t>(surface);
+ auto surface_index = static_cast<std::size_t>(material);
- if(surface_index >= NUM_SURFACES) {
+ if(surface_index >= world::VMAT_COUNT) {
// Surface index out of range
return nullptr;
}
@@ -39,48 +36,48 @@ static resource_ptr<SoundEffect> get_footsteps_effect(world::voxel_surface surfa void world::voxel_sounds::init(void)
{
- add_footsteps_effect(voxel_surface::DEFAULT, "sounds/surface/default1.wav");
- add_footsteps_effect(voxel_surface::DEFAULT, "sounds/surface/default2.wav");
- add_footsteps_effect(voxel_surface::DEFAULT, "sounds/surface/default3.wav");
- add_footsteps_effect(voxel_surface::DEFAULT, "sounds/surface/default4.wav");
+ add_footsteps_effect(VMAT_DEFAULT, "sounds/surface/default1.wav");
+ add_footsteps_effect(VMAT_DEFAULT, "sounds/surface/default2.wav");
+ add_footsteps_effect(VMAT_DEFAULT, "sounds/surface/default3.wav");
+ add_footsteps_effect(VMAT_DEFAULT, "sounds/surface/default4.wav");
- add_footsteps_effect(voxel_surface::DIRT, "sounds/surface/dirt1.wav");
+ add_footsteps_effect(VMAT_DIRT, "sounds/surface/dirt1.wav");
- add_footsteps_effect(voxel_surface::GRASS, "sounds/surface/grass1.wav");
- add_footsteps_effect(voxel_surface::GRASS, "sounds/surface/grass2.wav");
- add_footsteps_effect(voxel_surface::GRASS, "sounds/surface/grass3.wav");
+ add_footsteps_effect(VMAT_GRASS, "sounds/surface/grass1.wav");
+ add_footsteps_effect(VMAT_GRASS, "sounds/surface/grass2.wav");
+ add_footsteps_effect(VMAT_GRASS, "sounds/surface/grass3.wav");
- add_footsteps_effect(voxel_surface::GRAVEL, "sounds/surface/gravel1.wav");
+ add_footsteps_effect(VMAT_GRAVEL, "sounds/surface/gravel1.wav");
- add_footsteps_effect(voxel_surface::SAND, "sounds/surface/sand1.wav");
- add_footsteps_effect(voxel_surface::SAND, "sounds/surface/sand2.wav");
+ add_footsteps_effect(VMAT_SAND, "sounds/surface/sand1.wav");
+ add_footsteps_effect(VMAT_SAND, "sounds/surface/sand2.wav");
- add_footsteps_effect(voxel_surface::WOOD, "sounds/surface/wood1.wav");
- add_footsteps_effect(voxel_surface::WOOD, "sounds/surface/wood2.wav");
- add_footsteps_effect(voxel_surface::WOOD, "sounds/surface/wood3.wav");
+ add_footsteps_effect(VMAT_WOOD, "sounds/surface/wood1.wav");
+ add_footsteps_effect(VMAT_WOOD, "sounds/surface/wood2.wav");
+ add_footsteps_effect(VMAT_WOOD, "sounds/surface/wood3.wav");
}
void world::voxel_sounds::shutdown(void)
{
- for(std::size_t i = 0; i < NUM_SURFACES; ++i) {
+ for(std::size_t i = 0; i < world::VMAT_COUNT; ++i) {
footsteps_sounds[i].clear();
}
}
-resource_ptr<SoundEffect> world::voxel_sounds::get_footsteps(voxel_surface surface)
+resource_ptr<SoundEffect> world::voxel_sounds::get_footsteps(world::VoxelMaterial material)
{
- if(auto effect = get_footsteps_effect(surface)) {
+ if(auto effect = get_footsteps_effect(material)) {
return effect;
}
- if(auto effect = get_footsteps_effect(voxel_surface::DEFAULT)) {
+ if(auto effect = get_footsteps_effect(VMAT_DEFAULT)) {
return effect;
}
return nullptr;
}
-resource_ptr<SoundEffect> world::voxel_sounds::get_placebreak(voxel_surface surface)
+resource_ptr<SoundEffect> world::voxel_sounds::get_placebreak(world::VoxelMaterial material)
{
return nullptr;
}
diff --git a/game/client/world/voxel_sounds.hh b/game/client/world/voxel_sounds.hh index 09f5e2e..d0f3e07 100644 --- a/game/client/world/voxel_sounds.hh +++ b/game/client/world/voxel_sounds.hh @@ -2,7 +2,7 @@ #include "core/resource/resource.hh"
-#include "shared/world/voxel_registry.hh"
+#include "shared/world/voxel.hh"
struct SoundEffect;
@@ -14,6 +14,6 @@ void shutdown(void); namespace world::voxel_sounds
{
-resource_ptr<SoundEffect> get_footsteps(voxel_surface surface);
-resource_ptr<SoundEffect> get_placebreak(voxel_surface surface);
+resource_ptr<SoundEffect> get_footsteps(VoxelMaterial material);
+resource_ptr<SoundEffect> get_placebreak(VoxelMaterial material);
} // namespace world::voxel_sounds
|
