#include "client/window/inventory_window.hh" namespace client { namespace window { using iw = class inventory_window; bool iw::maybe_handle_mousebuttondown(const SDL_Event& event) noexcept { if (event.button.button != SDL_BUTTON_LEFT) { return false; } if (!this->is_inside(client::input::state.mouse_pos)) { return false; } const auto index = this->maybe_get_inventory_index(client::input::state.mouse_pos); if (!index.has_value()) { return false; } const auto& inventory = client::get_localplayer().inventory; if (inventory.contents[*index] != nullptr) { this->grabbed.emplace(*index); } return true; } static proto::packet make_swap_packet(const std::uint32_t& a, const std::uint32_t& b) noexcept { proto::packet ret; const auto packet = ret.mutable_item_swap_packet(); packet->set_index_a(a); packet->set_index_b(b); return ret; } bool iw::maybe_handle_mousebuttonup(const SDL_Event& event) noexcept { if (event.button.button != SDL_BUTTON_LEFT) { return false; } if (!this->grabbed.has_value()) { return false; } if (const auto index = this->maybe_get_inventory_index(input::state.mouse_pos); index.has_value() && index != *grabbed) { auto& inventory = client::get_localplayer().inventory; std::swap(inventory.contents[*grabbed], inventory.contents[*index]); // replicate on server state::connection->rsend_packet( make_swap_packet(static_cast(*grabbed), static_cast(*index))); } this->grabbed.reset(); return true; } std::optional iw::maybe_get_inventory_index(const glm::vec2& pos) const noexcept { const float item_size = this->get_item_size(); for (int x = 0; x < shared::player::INVENTORY_COLS; ++x) { for (int y = 0; y < shared::player::INVENTORY_ROWS; ++y) { const glm::vec2 off{this->pos + glm::vec2{OUTLINE_WIDTH, OUTLINE_WIDTH} + glm::vec2{x, y} * item_size}; if (!basic_window::is_inside(pos, off, glm::vec2{item_size, item_size})) { continue; } return x + y * shared::player::INVENTORY_COLS; } } return std::nullopt; } bool iw::maybe_handle_event(const SDL_Event& event) noexcept { switch (event.type) { case SDL_MOUSEBUTTONDOWN: return this->maybe_handle_mousebuttondown(event); case SDL_MOUSEBUTTONUP: return this->maybe_handle_mousebuttonup(event); } return basic_window::maybe_handle_event(event); } void iw::draw() noexcept { basic_window::draw(); const float item_size = this->get_item_size(); const auto& localplayer = client::get_localplayer(); client::render::draw_rectangle( {.pos = {.offset = {this->pos.x + static_cast( localplayer.get_active_item()) * item_size, this->pos.y}}, .size = {.offset = {item_size, item_size}}, .colour = {this->secondary_clr, 1.0f}}); for (int i = 1; i < shared::player::INVENTORY_COLS; ++i) { const float off = item_size * static_cast(i); client::render::draw_rectangle( {.pos = {.offset = {this->pos.x + off, this->pos.y + OUTLINE_WIDTH}}, .size = {.offset = {OUTLINE_WIDTH, item_size * shared::player::INVENTORY_ROWS - OUTLINE_WIDTH}}, .colour = {this->tertiary_clr, 1.0f}}); if (i <= shared::player::INVENTORY_ROWS) { client::render::draw_rectangle( {.pos = {.offset = {pos.x + OUTLINE_WIDTH, pos.y + off}}, .size = {.offset = {this->size.x - 2.0f * OUTLINE_WIDTH, OUTLINE_WIDTH}}, .colour = {this->tertiary_clr, 1.0f}}); } } const auto& inventory = localplayer.inventory; if (const auto index = this->maybe_get_inventory_index(client::input::state.mouse_pos); index.has_value()) { const glm::vec2 off{glm::vec2{*index % shared::player::INVENTORY_COLS, *index / shared::player::INVENTORY_COLS} * item_size}; client::render::draw_rectangle( {.pos = {.offset = this->pos + off + glm::vec2{OUTLINE_WIDTH, OUTLINE_WIDTH}}, .size = {.offset = glm::vec2{item_size, item_size} - glm::vec2{OUTLINE_WIDTH, OUTLINE_WIDTH}}, .colour = {this->secondary_clr, 1.0f}}); } for (int x = 0; x < shared::player::INVENTORY_COLS; ++x) { for (int y = 0; y < shared::player::INVENTORY_ROWS; ++y) { const auto index = static_cast( x + y * shared::player::INVENTORY_COLS); const auto& item = inventory.contents[index]; if (item == nullptr) { continue; } if (this->grabbed.has_value() && *this->grabbed == index) { continue; } const glm::vec2 off{glm::vec2{x, y} * item_size}; const auto item_ptr = dynamic_cast(&*item); if (item_ptr == nullptr) { continue; } item_ptr->draw(this->pos + off, glm::vec2{item_size, item_size}); client::render::draw_text( std::to_string(item->quantity), {.pos = {.offset = this->pos + off + glm::vec2{item_size * 0.75f, item_size * 0.2f}}, .offset_height = item_size * 0.40f, .colour = {this->font_colour, 1.0f}, .has_backing = false, .is_centered = true, .is_vcentered = true}); } } if (this->grabbed.has_value()) { const auto item_ptr = dynamic_cast(&*inventory.contents[*grabbed]); if (item_ptr != nullptr) { item_ptr->draw(client::input::state.mouse_pos - glm::vec2{item_size, item_size} * 0.5f, glm::vec2{item_size, item_size}); client::render::draw_text( std::to_string(item_ptr->quantity), {.pos = {.offset = client::input::state.mouse_pos + glm::vec2{item_size * 0.25f, item_size * -0.3f}}, .offset_height = item_size * 0.40f, .colour = {this->font_colour, 1.0f}, .has_backing = false, .is_centered = true, .is_vcentered = true}); } } } } // namespace window } // namespace client