summaryrefslogtreecommitdiffstats
path: root/game/client/gui
diff options
context:
space:
mode:
authoruntodesu <kirill@untode.su>2025-09-12 16:16:06 +0500
committeruntodesu <kirill@untode.su>2025-09-12 16:16:06 +0500
commitfc80fa024fc93dac6ea89461ef36f455c5e468a2 (patch)
tree7c4ea8f03b6778572d59784dc28b600e3f8f2268 /game/client/gui
parent12947aafcc6a6eb362cc454e2149796ec9265743 (diff)
parent522a7514012da86f7b9643179f0763746f3b232e (diff)
downloadvoxelius-fc80fa024fc93dac6ea89461ef36f455c5e468a2.tar.bz2
voxelius-fc80fa024fc93dac6ea89461ef36f455c5e468a2.zip
Merge pull request #15 from untodesu/metavoxels
Metavoxels
Diffstat (limited to 'game/client/gui')
-rw-r--r--game/client/gui/bother.cc8
-rw-r--r--game/client/gui/bother.hh4
-rw-r--r--game/client/gui/hotbar.cc19
-rw-r--r--game/client/gui/hotbar.hh9
-rw-r--r--game/client/gui/play_menu.cc92
-rw-r--r--game/client/gui/status_lines.cc4
-rw-r--r--game/client/gui/status_lines.hh2
-rw-r--r--game/client/gui/window_title.cc11
8 files changed, 89 insertions, 60 deletions
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());
}