aboutsummaryrefslogtreecommitdiff
path: root/src/client/window/inventory_window.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/window/inventory_window.cc')
-rw-r--r--src/client/window/inventory_window.cc196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/client/window/inventory_window.cc b/src/client/window/inventory_window.cc
new file mode 100644
index 0000000..5023f1d
--- /dev/null
+++ b/src/client/window/inventory_window.cc
@@ -0,0 +1,196 @@
+#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<std::uint32_t>(*grabbed),
+ static_cast<std::uint32_t>(*index)));
+ }
+
+ this->grabbed.reset();
+ return true;
+}
+
+std::optional<unsigned long>
+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<float>(
+ 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<float>(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<unsigned long>(
+ 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<client::item::item*>(&*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<client::item::item*>(&*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