2020-02-28 19:12:37 -08:00
|
|
|
//
|
|
|
|
// Created by aurailus on 2020-02-28.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "InventoryList.h"
|
|
|
|
|
2020-08-13 00:55:18 -07:00
|
|
|
#include "game/def/ItemDef.h"
|
|
|
|
#include "util/net/Serializer.h"
|
|
|
|
#include "lua/usertype/ItemStack.h"
|
|
|
|
#include "game/atlas/DefinitionAtlas.h"
|
2020-02-28 19:12:37 -08:00
|
|
|
|
2020-12-03 16:26:57 -08:00
|
|
|
InventoryList::InventoryList(SubgamePtr game, const std::string& name, const std::string& invName,
|
|
|
|
unsigned short size, unsigned short width) :
|
2020-11-08 22:11:58 -08:00
|
|
|
game(game),
|
|
|
|
name(name),
|
|
|
|
items(size),
|
|
|
|
width(width),
|
|
|
|
invName(invName) {}
|
2020-05-13 20:43:31 -07:00
|
|
|
|
2020-07-30 22:07:00 -07:00
|
|
|
std::string InventoryList::getName() const {
|
2020-11-08 22:11:58 -08:00
|
|
|
return name;
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
2020-11-08 22:11:58 -08:00
|
|
|
void InventoryList::setWidth(unsigned short newWidth) {
|
|
|
|
width = newWidth;
|
2020-07-21 19:33:26 -07:00
|
|
|
}
|
|
|
|
|
2020-02-28 19:12:37 -08:00
|
|
|
unsigned short InventoryList::getWidth() const {
|
2020-11-08 22:11:58 -08:00
|
|
|
return width;
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
2020-07-30 22:07:00 -07:00
|
|
|
void InventoryList::setLength(unsigned short length) {
|
2020-11-08 22:11:58 -08:00
|
|
|
items.resize(length);
|
2020-07-30 22:07:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned short InventoryList::getLength() const {
|
2020-11-08 22:11:58 -08:00
|
|
|
return items.size();
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// List Manipulation Functions
|
|
|
|
|
2020-11-08 22:11:58 -08:00
|
|
|
ItemStack InventoryList::placeStack(unsigned short i, const ItemStack& stack, bool playerInitiated) {
|
|
|
|
auto otherStack = getStack(i);
|
|
|
|
|
|
|
|
unsigned short allowedTake = otherStack.count;
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (playerInitiated) {
|
2020-12-05 21:17:46 -08:00
|
|
|
// auto allowTake = luaCallbacks[static_cast<int>(BlockDef::Callback::ALLOW_TAKE)];
|
2020-11-08 22:11:58 -08:00
|
|
|
// if (allowTake) allowedTake = std::min(static_cast<unsigned short>(
|
|
|
|
// allowTake(i+1, LuaItemStack(otherStack, defs))), allowedTake);
|
2020-07-30 22:07:00 -07:00
|
|
|
// }
|
2020-11-08 22:11:58 -08:00
|
|
|
unsigned short allowedPut = stack.count;
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (playerInitiated) {
|
2020-12-05 21:17:46 -08:00
|
|
|
// auto allowPut = luaCallbacks[static_cast<int>(BlockDef::Callback::ALLOW_PUT)];
|
2020-11-08 22:11:58 -08:00
|
|
|
// if (allowPut) allowedPut = std::min(static_cast<unsigned short>(
|
|
|
|
// allowPut(i+1, LuaItemStack(stack, defs))), allowedPut);
|
2020-07-30 22:07:00 -07:00
|
|
|
// }
|
2020-02-28 19:12:37 -08:00
|
|
|
|
2020-12-05 21:17:46 -08:00
|
|
|
// sol::function on_put = luaCallbacks[static_cast<int>(BlockDef::Callback::ON_PUT)];
|
|
|
|
// sol::function on_take = luaCallbacks[static_cast<int>(BlockDef::Callback::ON_TAKE)];
|
2020-11-08 22:11:58 -08:00
|
|
|
|
|
|
|
if (stack.count == 0) {
|
|
|
|
if (allowedTake == otherStack.count) setStack(i, { DefinitionAtlas::AIR, 0 });
|
|
|
|
else setStack(i, { otherStack.id, static_cast<unsigned short>(otherStack.count - allowedTake) });
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
|
2020-11-08 22:11:58 -08:00
|
|
|
return { otherStack.id, allowedTake };
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (otherStack.count) {
|
|
|
|
if (otherStack.id == stack.id) {
|
2021-09-03 14:22:58 -07:00
|
|
|
unsigned short maxStack = game->getDefs().fromId(stack.id).maxStack;
|
2020-11-08 22:11:58 -08:00
|
|
|
if (allowedPut >= stack.count && allowedPut + otherStack.count < maxStack) {
|
|
|
|
setStack(i, { stack.id, static_cast<unsigned short>(otherStack.count + allowedPut) });
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (on_put) on_put(i+1, LuaItemStack(otherStack, defs));
|
2020-11-08 22:11:58 -08:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
else if (allowedPut > 0) {
|
|
|
|
allowedPut = std::min(allowedPut, static_cast<unsigned short>(maxStack - otherStack.count));
|
|
|
|
setStack(i, { stack.id, static_cast<unsigned short>(otherStack.count + allowedPut) });
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
|
2020-11-08 22:11:58 -08:00
|
|
|
return { stack.id, static_cast<unsigned short>(stack.count - allowedPut) };
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
allowedTake = std::min(allowedTake, static_cast<unsigned short>(maxStack - stack.count));
|
|
|
|
setStack(i, { stack.id, static_cast<unsigned short>(otherStack.count - allowedTake) });
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
|
2020-11-08 22:11:58 -08:00
|
|
|
return { stack.id, static_cast<unsigned short>(stack.count + allowedTake) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (stack.count <= allowedPut && otherStack.count <= allowedTake) {
|
|
|
|
setStack(i, stack);
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
|
|
|
|
// if (on_take) on_take(i+1, LuaItemStack(otherStack, defs));
|
2020-11-08 22:11:58 -08:00
|
|
|
return otherStack;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return stack;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setStack(i, { stack.id, static_cast<unsigned short>(otherStack.count + allowedPut) });
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
|
2020-11-08 22:11:58 -08:00
|
|
|
return { stack.id, static_cast<unsigned short>(stack.count - allowedPut) };
|
|
|
|
}
|
|
|
|
}
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ItemStack InventoryList::splitStack(unsigned short i, bool playerInitiated) {
|
2020-11-08 22:11:58 -08:00
|
|
|
auto stack = getStack(i);
|
|
|
|
|
|
|
|
unsigned short allowedTake = stack.count;
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (playerInitiated) {
|
2020-12-05 21:17:46 -08:00
|
|
|
// auto allowTake = luaCallbacks[static_cast<int>(BlockDef::Callback::ALLOW_TAKE)];
|
2020-11-08 22:11:58 -08:00
|
|
|
// if (allowTake) allowedTake = std::min(static_cast<unsigned short>(
|
|
|
|
// allowTake(i + 1, LuaItemStack(stack, defs))), allowedTake);
|
2020-07-30 22:07:00 -07:00
|
|
|
// }
|
2020-11-08 22:11:58 -08:00
|
|
|
|
|
|
|
unsigned short initialCount = stack.count;
|
|
|
|
unsigned short takeCount = std::min(static_cast<unsigned short>(ceil(initialCount / 2.f)), allowedTake);
|
|
|
|
|
|
|
|
setStack(i, { stack.id, static_cast<unsigned short>(initialCount - takeCount) });
|
2020-12-05 21:17:46 -08:00
|
|
|
// sol::function on_take = luaCallbacks[static_cast<int>(BlockDef::Callback::ON_TAKE)];
|
2020-07-30 22:07:00 -07:00
|
|
|
// if (on_take) on_take(i+1, stack);
|
2020-11-08 22:11:58 -08:00
|
|
|
return { stack.id, takeCount };
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ItemStack InventoryList::addStack(ItemStack stack, bool playerInitiated) {
|
2021-09-03 14:22:58 -07:00
|
|
|
unsigned short maxStack = game->getDefs().fromId(stack.id).maxStack;
|
2020-11-08 22:11:58 -08:00
|
|
|
|
|
|
|
unsigned short i = 0;
|
|
|
|
while (i < items.size() && stack.count > 0) {
|
|
|
|
if (items[i].count == 0) {
|
|
|
|
if (stack.count <= maxStack) {
|
|
|
|
items[i] = stack;
|
|
|
|
manipulated();
|
|
|
|
return ItemStack{};
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
items[i] = stack;
|
|
|
|
items[i].count = maxStack;
|
|
|
|
stack.count -= maxStack;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (items[i].id == stack.id) {
|
|
|
|
unsigned int fits = maxStack - items[i].count;
|
|
|
|
if (fits >= stack.count) {
|
|
|
|
items[i].count += stack.count;
|
|
|
|
manipulated();
|
|
|
|
return ItemStack{};
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
stack.count -= fits;
|
|
|
|
items[i].count += fits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
manipulated();
|
|
|
|
return stack;
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
2020-11-08 22:11:58 -08:00
|
|
|
unsigned short InventoryList::stackFits(const ItemStack& stack) {
|
2021-09-03 14:22:58 -07:00
|
|
|
unsigned short maxStack = game->getDefs().fromId(stack.id).maxStack;
|
2020-11-08 22:11:58 -08:00
|
|
|
|
|
|
|
unsigned short i = 0;
|
|
|
|
unsigned short fits = 0;
|
|
|
|
|
|
|
|
while (i < items.size() && fits < stack.count) {
|
|
|
|
if (items[i].count == 0) {
|
|
|
|
fits += std::min(static_cast<unsigned short>(maxStack), stack.count);
|
|
|
|
}
|
|
|
|
else if (items[i].id == stack.id) {
|
|
|
|
unsigned int canfit = maxStack - items[i].count;
|
|
|
|
if (canfit >= stack.count - fits) fits += stack.count - fits;
|
|
|
|
else fits = stack.count;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fits;
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ItemStack InventoryList::takeStack(ItemStack request, bool playerInitiated) {
|
2020-11-08 22:11:58 -08:00
|
|
|
unsigned short i = 0;
|
|
|
|
unsigned short to_remove = request.count;
|
|
|
|
|
|
|
|
while (i < items.size() && request.count > 0) {
|
|
|
|
if (items[i].id == request.id) {
|
|
|
|
unsigned int can_take = items[i].count;
|
|
|
|
if (can_take >= to_remove) {
|
|
|
|
items[i].count -= to_remove;
|
|
|
|
manipulated();
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
to_remove -= can_take;
|
|
|
|
items[i] = ItemStack{};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
request.count = (request.count - to_remove);
|
|
|
|
manipulated();
|
|
|
|
return request;
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ItemStack InventoryList::removeStack(unsigned short ind, unsigned short count) {
|
2020-11-08 22:11:58 -08:00
|
|
|
auto stack = getStack(ind);
|
|
|
|
if (count >= stack.count) {
|
|
|
|
setStack(ind, { DefinitionAtlas::AIR, 0 });
|
|
|
|
return stack;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
stack.count -= count;
|
|
|
|
setStack(ind, stack);
|
|
|
|
stack.count = count;
|
|
|
|
return stack;
|
|
|
|
}
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
2020-08-02 17:16:40 -07:00
|
|
|
void InventoryList::interact(InventoryListPtr cursor, bool primary, unsigned short ind) {
|
2020-11-08 22:11:58 -08:00
|
|
|
if (primary) {
|
|
|
|
cursor->setStack(0, placeStack(ind, cursor->getStack(0), true));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
auto handStack = cursor->getStack(0);
|
|
|
|
if (handStack.count == 0) {
|
|
|
|
cursor->setStack(0, splitStack(ind, true));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
auto listStack = getStack(ind);
|
2020-12-03 16:26:57 -08:00
|
|
|
if (listStack.id <= 1 || listStack.id == handStack.id) {
|
2020-11-08 22:11:58 -08:00
|
|
|
auto overflow = placeStack(ind, { handStack.id, 1 }, true);
|
2020-12-03 16:26:57 -08:00
|
|
|
handStack.count = handStack.count - 1 + overflow.count;
|
2020-11-08 22:11:58 -08:00
|
|
|
if (handStack.count == 0) handStack.id = 0;
|
|
|
|
cursor->setStack(0, handStack);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cursor->setStack(0, placeStack(ind, cursor->getStack(0), true));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-01 14:33:47 -08:00
|
|
|
}
|
|
|
|
|
2020-02-28 19:12:37 -08:00
|
|
|
ItemStack InventoryList::getStack(unsigned short i) const {
|
2020-11-08 22:11:58 -08:00
|
|
|
return items[i];
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
2020-11-08 22:11:58 -08:00
|
|
|
void InventoryList::setStack(unsigned short i, const ItemStack& stack) {
|
|
|
|
if (stack == getStack(i)) return;
|
|
|
|
items[i] = stack;
|
|
|
|
manipulated();
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
2020-07-30 22:07:00 -07:00
|
|
|
Packet InventoryList::createPacket() {
|
2020-12-03 16:26:57 -08:00
|
|
|
Serializer s {};
|
2020-11-08 22:11:58 -08:00
|
|
|
|
|
|
|
s.append<std::string>(invName)
|
|
|
|
.append<std::string>(name)
|
|
|
|
.append<unsigned int>(items.size())
|
|
|
|
.append<unsigned int>(width);
|
|
|
|
|
|
|
|
for (auto& stack : items) {
|
|
|
|
s.append<unsigned short>(stack.count);
|
|
|
|
s.append<unsigned int>(stack.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
return s.packet(Packet::Type::INV_DATA, false);
|
2020-02-28 19:12:37 -08:00
|
|
|
}
|
|
|
|
|
2020-07-30 22:07:00 -07:00
|
|
|
//void InventoryList::setLuaCallback(InventoryList::Callback type, sol::protected_function cb) {
|
|
|
|
// luaCallbacks[static_cast<size_t>(type)] = cb;
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//sol::protected_function InventoryList::getLuaCallback(InventoryList::Callback type) {
|
|
|
|
// return luaCallbacks[static_cast<size_t>(type)];
|
|
|
|
//}
|
|
|
|
|
2020-08-02 17:16:40 -07:00
|
|
|
SubgamePtr InventoryList::getGame() {
|
2020-11-08 22:11:58 -08:00
|
|
|
return game;
|
2020-07-21 19:33:26 -07:00
|
|
|
}
|