Parent implemetation for Server/Local InventoryList shared methods

master
Nicole Collings 2020-02-28 19:12:37 -08:00
parent 7c0e1cefd7
commit 5cd56de9d0
8 changed files with 307 additions and 531 deletions

View File

@ -313,6 +313,6 @@ set(ZEPHA_SRC
lua/api/class/LocalLuaInventory.cpp
lua/api/class/LocalLuaInventory.h
lua/api/class/LocalLuaInventoryList.cpp
lua/api/class/LocalLuaInventoryList.h game/inventory/InventoryRefs.cpp game/inventory/InventoryRefs.h)
lua/api/class/LocalLuaInventoryList.h game/inventory/InventoryRefs.cpp game/inventory/InventoryRefs.h game/inventory/InventoryList.cpp game/inventory/InventoryList.h)
add_library (Zepha_Core ${ZEPHA_SRC})

View File

@ -0,0 +1,223 @@
//
// Created by aurailus on 2020-02-28.
//
#include "InventoryList.h"
#include "../../lua/api/class/LuaItemStack.h"
unsigned short InventoryList::getLength() const {
return itemstacks.size();
}
unsigned short InventoryList::getWidth() const {
return width;
}
std::string InventoryList::getName() const {
return listName;
}
// List Manipulation Functions
ItemStack InventoryList::placeStack(unsigned short i, const ItemStack &stack, bool playerInitiated) {
auto otherStack = getStack(i);
unsigned short allowedTake = otherStack.count;
if (playerInitiated) {
auto allowTake = luaCallbacks[static_cast<int>(Callback::ALLOW_TAKE)];
if (allowTake) allowedTake = std::min(static_cast<unsigned short>(allowTake(i+1, LuaItemStack(otherStack, defs))), allowedTake);
}
unsigned short allowedPut = stack.count;
if (playerInitiated) {
auto allowPut = luaCallbacks[static_cast<int>(Callback::ALLOW_PUT)];
if (allowPut) allowedPut = std::min(static_cast<unsigned short>(allowPut(i+1, LuaItemStack(stack, defs))), allowedPut);
}
sol::function on_put = luaCallbacks[static_cast<int>(Callback::ON_PUT)];
sol::function on_take = luaCallbacks[static_cast<int>(Callback::ON_TAKE)];
if (stack.count == 0) {
if (allowedTake == otherStack.count) setStack(i, {});
else setStack(i, {otherStack.id, static_cast<unsigned short>(otherStack.count - allowedTake)});
if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return {otherStack.id, allowedTake};
}
else {
if (otherStack.count) {
if (otherStack.id == stack.id) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
if (allowedPut >= stack.count && allowedPut + otherStack.count < maxStack) {
setStack(i, {stack.id, static_cast<unsigned short>(otherStack.count + allowedPut)});
if (on_put) on_put(i+1, LuaItemStack(otherStack, defs));
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)});
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
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)});
if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return {stack.id, static_cast<unsigned short>(stack.count + allowedTake)};
}
}
else {
if (stack.count <= allowedPut && otherStack.count <= allowedTake) {
setStack(i, stack);
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
if (on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return otherStack;
}
else {
return stack;
}
}
}
else {
setStack(i, {stack.id, static_cast<unsigned short>(otherStack.count + allowedPut)});
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
return {stack.id, static_cast<unsigned short>(stack.count - allowedPut)};
}
}
}
ItemStack InventoryList::splitStack(unsigned short i, bool playerInitiated) {
auto stack = getStack(i);
unsigned short allowedTake = stack.count;
if (playerInitiated) {
auto allowTake = luaCallbacks[static_cast<int>(Callback::ALLOW_TAKE)];
if (allowTake) allowedTake = std::min(static_cast<unsigned short>(allowTake(i + 1, LuaItemStack(stack, defs))), allowedTake);
}
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)});
sol::function on_take = luaCallbacks[static_cast<int>(Callback::ON_TAKE)];
if (on_take) on_take(i+1, stack);
return {stack.id, takeCount};
}
ItemStack InventoryList::addStack(ItemStack stack, bool playerInitiated) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
unsigned short i = 0;
while (i < itemstacks.size() && stack.count > 0) {
if (itemstacks[i].count == 0) {
if (stack.count <= maxStack) {
itemstacks[i] = stack;
manipulated();
return ItemStack{};
}
else {
itemstacks[i] = stack;
itemstacks[i].count = maxStack;
stack.count -= maxStack;
}
}
else if (itemstacks[i].id == stack.id) {
unsigned int fits = maxStack - itemstacks[i].count;
if (fits >= stack.count) {
itemstacks[i].count += stack.count;
manipulated();
return ItemStack {};
}
else {
stack.count -= fits;
itemstacks[i].count += fits;
}
}
i++;
}
manipulated();
return stack;
}
unsigned short InventoryList::stackFits(const ItemStack &stack) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
unsigned short i = 0;
unsigned short fits = 0;
while (i < itemstacks.size() && fits < stack.count) {
if (itemstacks[i].count == 0) {
fits += std::min(static_cast<unsigned short>(maxStack), stack.count);
}
else if (itemstacks[i].id == stack.id) {
unsigned int canfit = maxStack - itemstacks[i].count;
if (canfit >= stack.count - fits) {
fits += stack.count - fits;
}
else {
fits = stack.count;
}
}
i++;
}
return fits;
}
ItemStack InventoryList::takeStack(ItemStack request, bool playerInitiated) {
unsigned short i = 0;
unsigned short to_remove = request.count;
while (i < itemstacks.size() && request.count > 0) {
if (itemstacks[i].id == request.id) {
unsigned int can_take = itemstacks[i].count;
if (can_take >= to_remove) {
itemstacks[i].count -= to_remove;
manipulated();
return request;
}
else {
to_remove -= can_take;
itemstacks[i] = ItemStack {};
}
}
i++;
}
request.count = (request.count - to_remove);
manipulated();
return request;
}
ItemStack InventoryList::removeStack(unsigned short ind, unsigned short count) {
auto stack = getStack(ind);
if (count >= stack.count) {
setStack(ind, {0, 0});
return stack;
}
else {
stack.count -= count;
setStack(ind, stack);
stack.count = count;
return stack;
}
}
ItemStack InventoryList::getStack(unsigned short i) const {
return itemstacks[i];
}
void InventoryList::setStack(unsigned short i, const ItemStack &stack) {
if (stack != getStack(i)) {
itemstacks[i] = stack;
manipulated();
}
}
void InventoryList::setLuaCallback(InventoryList::Callback type, sol::function cb) {
luaCallbacks[static_cast<size_t>(type)] = cb;
}
sol::function InventoryList::getLuaCallback(InventoryList::Callback type) {
return luaCallbacks[static_cast<size_t>(type)];
}

View File

@ -0,0 +1,59 @@
//
// Created by aurailus on 2020-02-28.
//
#pragma once
#include <string>
#include "ItemStack.h"
#include "../../def/DefinitionAtlas.h"
class InventoryList {
public:
enum class Callback {
ALLOW_TAKE,
ALLOW_PUT,
ON_TAKE,
ON_PUT
};
InventoryList(DefinitionAtlas& defs) : defs(defs) {};
InventoryList(DefinitionAtlas& defs, const std::string& invName, const std::string& listName, unsigned short size, unsigned short width) :
defs(defs), invName(invName), listName(listName), width(width), itemstacks(size) {};
unsigned short getLength() const;
unsigned short getWidth() const;
std::string getName() const;
// Place the stack at i into the existing stack, returning overflow or other stack.
virtual ItemStack placeStack(unsigned short i, const ItemStack& stack, bool playerInitiated = false);
// Split the stack at i and return half of it, rounded up
virtual ItemStack splitStack(unsigned short i, bool playerInitiated = false);
// Adds as much of `stack` to the inventory as possible, returns leftover.
virtual ItemStack addStack(ItemStack stack, bool playerInitiated = false);
// Returns how many of `stack`'s items fit, from 0 to stack.count.
virtual unsigned short stackFits(const ItemStack& stack);
// Attempts to remove the usertype and amount of items specified by `stack`. Returns actual ItemStack of what was removed.
virtual ItemStack takeStack(ItemStack request, bool playerInitiated = false);
// Removes up to count items from ind, returns the items removed
virtual ItemStack removeStack(unsigned short ind, unsigned short count);
ItemStack getStack(unsigned short i) const;
void setStack(unsigned short i, const ItemStack& stack);
sol::function getLuaCallback(Callback type);
void setLuaCallback(Callback type, sol::function cb);
DefinitionAtlas& defs;
protected:
virtual void manipulated() = 0;
std::string invName {}, listName {};
unsigned short width = 0;
std::vector<ItemStack> itemstacks {};
std::array<sol::function, 4> luaCallbacks = {};
};

View File

@ -5,7 +5,7 @@
#include "LocalInventory.h"
void LocalInventory::createList(std::string name, unsigned short length, unsigned short width, bool maintain) {
lists.insert({name, {(maintain ? -1 : 0), std::make_shared<LocalInventoryList>(defs, name, length, width)}});
lists.insert({name, {(maintain ? -1 : 0), std::make_shared<LocalInventoryList>(defs, this->name, name, length, width)}});
}
std::shared_ptr<LocalInventoryList> LocalInventory::operator[](std::string name) {

View File

@ -2,243 +2,23 @@
// Created by aurailus on 2019-10-29.
//
#include <iostream>
#include <algorithm>
#include "LocalInventoryList.h"
#include "../../lua/api/class/LuaItemStack.h"
LocalInventoryList::LocalInventoryList(DefinitionAtlas& defs, const std::string& name, unsigned short size, unsigned short width) :
defs(defs),
name(name),
itemstacks(size),
width(width) {}
LocalInventoryList::LocalInventoryList(DefinitionAtlas& defs, const std::string& invName,
const std::string& listName, unsigned short size, unsigned short width) :
InventoryList(defs, invName, listName, size, width) {}
void LocalInventoryList::setData(unsigned int size, unsigned int width, std::vector<ItemStack> stacks) {
this->width = width;
this->itemstacks = stacks;
triggerCallback();
manipulated();
}
void LocalInventoryList::setGuiCallback(std::function<void()> cb) {
this->guiCallback = cb;
}
void LocalInventoryList::setLuaCallback(LocalInventoryList::Callback type, sol::function cb) {
luaCallbacks[static_cast<size_t>(type)] = cb;
}
sol::function LocalInventoryList::getLuaCallback(LocalInventoryList::Callback type) {
return luaCallbacks[static_cast<size_t>(type)];
}
ItemStack LocalInventoryList::getStack(unsigned short i) {
return itemstacks[i];
}
void LocalInventoryList::setStack(unsigned short i, const ItemStack &stack) {
if (stack != getStack(i)) {
itemstacks[i] = stack;
triggerCallback();
}
}
ItemStack LocalInventoryList::placeStack(unsigned short i, const ItemStack &stack, bool playerInitiated) {
auto otherStack = getStack(i);
unsigned short allowedTake = otherStack.count;
if (playerInitiated) {
auto allowTake = luaCallbacks[static_cast<int>(Callback::ALLOW_TAKE)];
if (allowTake) allowedTake = std::min(static_cast<unsigned short>(allowTake(i+1, LuaItemStack(otherStack, defs))), allowedTake);
}
unsigned short allowedPut = stack.count;
if (playerInitiated) {
auto allowPut = luaCallbacks[static_cast<int>(Callback::ALLOW_PUT)];
if (allowPut) allowedPut = std::min(static_cast<unsigned short>(allowPut(i+1, LuaItemStack(stack, defs))), allowedPut);
}
sol::function on_put = luaCallbacks[static_cast<int>(Callback::ON_PUT)];
sol::function on_take = luaCallbacks[static_cast<int>(Callback::ON_TAKE)];
if (stack.count == 0) {
if (allowedTake == otherStack.count) setStack(i, {});
else setStack(i, {otherStack.id, static_cast<unsigned short>(otherStack.count - allowedTake)});
if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return {otherStack.id, allowedTake};
}
else {
if (otherStack.count) {
if (otherStack.id == stack.id) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
if (allowedPut >= stack.count && allowedPut + otherStack.count < maxStack) {
setStack(i, {stack.id, static_cast<unsigned short>(otherStack.count + allowedPut)});
if (on_put) on_put(i+1, LuaItemStack(otherStack, defs));
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)});
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
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)});
if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return {stack.id, static_cast<unsigned short>(stack.count + allowedTake)};
}
}
else {
if (stack.count <= allowedPut && otherStack.count <= allowedTake) {
setStack(i, stack);
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
if (on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return otherStack;
}
else {
return stack;
}
}
}
else {
setStack(i, {stack.id, static_cast<unsigned short>(otherStack.count + allowedPut)});
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
return {stack.id, static_cast<unsigned short>(stack.count - allowedPut)};
}
}
}
ItemStack LocalInventoryList::splitStack(unsigned short i, bool playerInitiated) {
auto stack = getStack(i);
unsigned short allowedTake = stack.count;
if (playerInitiated) {
auto allowTake = luaCallbacks[static_cast<int>(Callback::ALLOW_TAKE)];
if (allowTake) allowedTake = std::min(static_cast<unsigned short>(allowTake(i + 1, LuaItemStack(stack, defs))), allowedTake);
}
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)});
sol::function on_take = luaCallbacks[static_cast<int>(Callback::ON_TAKE)];
if (on_take) on_take(i+1, stack);
return {stack.id, takeCount};
}
ItemStack LocalInventoryList::addStack(ItemStack stack, bool playerInitiated) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
unsigned short i = 0;
while (i < itemstacks.size() && stack.count > 0) {
if (itemstacks[i].count == 0) {
if (stack.count <= maxStack) {
itemstacks[i] = stack;
triggerCallback();
return ItemStack{};
}
else {
itemstacks[i] = stack;
itemstacks[i].count = maxStack;
stack.count -= maxStack;
}
}
else if (itemstacks[i].id == stack.id) {
unsigned int fits = maxStack - itemstacks[i].count;
if (fits >= stack.count) {
itemstacks[i].count += stack.count;
triggerCallback();
return ItemStack {};
}
else {
stack.count -= fits;
itemstacks[i].count += fits;
}
}
i++;
}
triggerCallback();
return stack;
}
unsigned short LocalInventoryList::stackFits(const ItemStack &stack) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
unsigned short i = 0;
unsigned short fits = 0;
while (i < itemstacks.size() && fits < stack.count) {
if (itemstacks[i].count == 0) {
fits += std::min(static_cast<unsigned short>(maxStack), stack.count);
}
else if (itemstacks[i].id == stack.id) {
unsigned int canfit = maxStack - itemstacks[i].count;
if (canfit >= stack.count - fits) {
fits += stack.count - fits;
}
else {
fits = stack.count;
}
}
i++;
}
return fits;
}
ItemStack LocalInventoryList::takeStack(ItemStack request, bool playerInitiated) {
unsigned short i = 0;
unsigned short to_remove = request.count;
while (i < itemstacks.size() && request.count > 0) {
if (itemstacks[i].id == request.id) {
unsigned int can_take = itemstacks[i].count;
if (can_take >= to_remove) {
itemstacks[i].count -= to_remove;
triggerCallback();
return request;
}
else {
to_remove -= can_take;
itemstacks[i] = ItemStack {};
}
}
i++;
}
request.count = (request.count - to_remove);
triggerCallback();
return request;
}
ItemStack LocalInventoryList::removeStack(unsigned short ind, unsigned short count) {
auto stack = getStack(ind);
if (count >= stack.count) {
setStack(ind, {0, 0});
return stack;
}
else {
stack.count -= count;
setStack(ind, stack);
stack.count = count;
return stack;
}
}
void LocalInventoryList::triggerCallback() {
void LocalInventoryList::manipulated(){
if (guiCallback != nullptr) guiCallback();
}
unsigned short LocalInventoryList::getLength() {
return itemstacks.size();
}
unsigned short LocalInventoryList::getWidth() {
return width;
}
std::string LocalInventoryList::getName() {
return name;
}

View File

@ -4,54 +4,17 @@
#pragma once
#include <list>
#include <vector>
#include <functional>
#include "InventoryList.h"
#include "ItemStack.h"
class LocalInventoryList {
class LocalInventoryList : public InventoryList {
public:
enum class Callback { ALLOW_TAKE, ALLOW_PUT, ON_TAKE, ON_PUT };
LocalInventoryList(DefinitionAtlas& defs, const std::string& name, unsigned short size, unsigned short width);
unsigned short getLength();
unsigned short getWidth();
std::string getName();
LocalInventoryList(DefinitionAtlas& defs, const std::string& invName,
const std::string& listName, unsigned short size, unsigned short width);
void setData(unsigned int size, unsigned int width, std::vector<ItemStack> stacks);
// Place the stack at i into the existing stack, returning overflow or other stack.
ItemStack placeStack(unsigned short i, const ItemStack& stack, bool playerInitiated = false);
// Split the stack at i and return half of it, rounded up
ItemStack splitStack(unsigned short i, bool playerInitiated = false);
// Adds as much of `stack` to the inventory as possible, returns leftover.
ItemStack addStack(ItemStack stack, bool playerInitiated = false);
// Returns how many of `stack`'s items fit, from 0 to stack.count.
unsigned short stackFits(const ItemStack& stack);
// Attempts to remove the type and amount of items specified by `stack`. Returns actual ItemStack of what was removed.
ItemStack takeStack(ItemStack request, bool playerInitiated = false);
void setStack(unsigned short i, const ItemStack& stack);
ItemStack getStack(unsigned short i);
// Removes up to count items from ind, returns the items removed
ItemStack removeStack(unsigned short ind, unsigned short count);
void setGuiCallback(std::function<void()> cb);
void setLuaCallback(Callback type, sol::function cb);
sol::function getLuaCallback(Callback type);
DefinitionAtlas& defs;
private:
void triggerCallback();
std::vector<ItemStack> itemstacks {};
unsigned short width = 0;
std::string name;
void manipulated() override;
std::function<void()> guiCallback = nullptr;
std::array<sol::function, 4> luaCallbacks = {};
};

View File

@ -12,232 +12,16 @@
#include "../../server/conn/ClientList.h"
#include "../../lua/api/class/LuaItemStack.h"
ServerInventoryList::ServerInventoryList(DefinitionAtlas& defs, ClientList* list, const std::string& invName, const std::string& name, unsigned short size, unsigned short width) :
defs(defs),
name(name),
width(width),
clients(list),
invName(invName),
itemstacks(size) {}
ServerInventoryList::ServerInventoryList(DefinitionAtlas& defs, ClientList* list,
const std::string& invName, const std::string& listName, unsigned short size, unsigned short width) :
void ServerInventoryList::setLuaCallback(ServerInventoryList::Callback type, sol::function cb) {
luaCallbacks[static_cast<size_t>(type)] = cb;
}
InventoryList(defs, invName, listName, size, width),
clients(list) {}
sol::function ServerInventoryList::getLuaCallback(ServerInventoryList::Callback type) {
return luaCallbacks[static_cast<size_t>(type)];
}
ItemStack ServerInventoryList::getStack(unsigned short i) {
return itemstacks[i];
}
void ServerInventoryList::setStack(unsigned short i, const ItemStack &stack) {
if (stack != getStack(i)) {
itemstacks[i] = stack;
setDirty();
}
}
ItemStack ServerInventoryList::placeStack(unsigned short i, const ItemStack &stack, bool playerInitiated) {
auto otherStack = getStack(i);
unsigned short allowedTake = otherStack.count;
if (playerInitiated) {
auto allowTake = luaCallbacks[static_cast<int>(Callback::ALLOW_TAKE)];
if (allowTake) allowedTake = std::min(static_cast<unsigned short>(allowTake(i+1, LuaItemStack(otherStack, defs))), allowedTake);
}
unsigned short allowedPut = stack.count;
if (playerInitiated) {
auto allowPut = luaCallbacks[static_cast<int>(Callback::ALLOW_PUT)];
if (allowPut) allowedPut = std::min(static_cast<unsigned short>(allowPut(i+1, LuaItemStack(stack, defs))), allowedPut);
}
sol::function on_put = luaCallbacks[static_cast<int>(Callback::ON_PUT)];
sol::function on_take = luaCallbacks[static_cast<int>(Callback::ON_TAKE)];
if (stack.count == 0) {
if (allowedTake == otherStack.count) setStack(i, {});
else setStack(i, {otherStack.id, static_cast<unsigned short>(otherStack.count - allowedTake)});
if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return {otherStack.id, allowedTake};
}
else {
if (otherStack.count) {
if (otherStack.id == stack.id) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
if (allowedPut >= stack.count && allowedPut + otherStack.count < maxStack) {
setStack(i, {stack.id, static_cast<unsigned short>(otherStack.count + allowedPut)});
if (on_put) on_put(i+1, LuaItemStack(otherStack, defs));
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)});
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
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)});
if (allowedTake > 0 && on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return {stack.id, static_cast<unsigned short>(stack.count + allowedTake)};
}
}
else {
if (stack.count <= allowedPut && otherStack.count <= allowedTake) {
setStack(i, stack);
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
if (on_take) on_take(i+1, LuaItemStack(otherStack, defs));
return otherStack;
}
else {
return stack;
}
}
}
else {
setStack(i, {stack.id, static_cast<unsigned short>(otherStack.count + allowedPut)});
if (allowedPut > 0 && on_put) on_put(i+1, LuaItemStack(otherStack, defs));
return {stack.id, static_cast<unsigned short>(stack.count - allowedPut)};
}
}
}
ItemStack ServerInventoryList::splitStack(unsigned short i, bool playerInitiated) {
auto stack = getStack(i);
unsigned short allowedTake = stack.count;
if (playerInitiated) {
auto allowTake = luaCallbacks[static_cast<int>(Callback::ALLOW_TAKE)];
if (allowTake) allowedTake = std::min(static_cast<unsigned short>(allowTake(i + 1, LuaItemStack(stack, defs))), allowedTake);
}
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)});
sol::function on_take = luaCallbacks[static_cast<int>(Callback::ON_TAKE)];
if (on_take) on_take(i+1, stack);
return {stack.id, takeCount};
}
ItemStack ServerInventoryList::addStack(ItemStack stack, bool playerInitiated) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
unsigned short i = 0;
while (i < itemstacks.size() && stack.count > 0) {
if (itemstacks[i].count == 0) {
if (stack.count <= maxStack) {
itemstacks[i] = stack;
setDirty();
return ItemStack{};
}
else {
itemstacks[i] = stack;
itemstacks[i].count = maxStack;
stack.count -= maxStack;
}
}
else if (itemstacks[i].id == stack.id) {
unsigned int fits = maxStack - itemstacks[i].count;
if (fits >= stack.count) {
itemstacks[i].count += stack.count;
setDirty();
return ItemStack {};
}
else {
stack.count -= fits;
itemstacks[i].count += fits;
}
}
i++;
}
setDirty();
return stack;
}
unsigned short ServerInventoryList::stackFits(const ItemStack &stack) {
unsigned short maxStack = defs.fromId(stack.id).maxStackSize;
unsigned short i = 0;
unsigned short fits = 0;
while (i < itemstacks.size() && fits < stack.count) {
if (itemstacks[i].count == 0) {
fits += std::min(static_cast<unsigned short>(maxStack), stack.count);
}
else if (itemstacks[i].id == stack.id) {
unsigned int canfit = maxStack - itemstacks[i].count;
if (canfit >= stack.count - fits) {
fits += stack.count - fits;
}
else {
fits = stack.count;
}
}
i++;
}
return fits;
}
ItemStack ServerInventoryList::takeStack(ItemStack request, bool playerInitiated) {
unsigned short i = 0;
unsigned short to_remove = request.count;
while (i < itemstacks.size() && request.count > 0) {
if (itemstacks[i].id == request.id) {
unsigned int can_take = itemstacks[i].count;
if (can_take >= to_remove) {
itemstacks[i].count -= to_remove;
setDirty();
return request;
}
else {
to_remove -= can_take;
itemstacks[i] = ItemStack {};
}
}
i++;
}
request.count = (request.count - to_remove);
setDirty();
return request;
}
ItemStack ServerInventoryList::removeStack(unsigned short ind, unsigned short count) {
auto stack = getStack(ind);
if (count >= stack.count) {
setStack(ind, {0, 0});
return stack;
}
else {
stack.count -= count;
setStack(ind, stack);
stack.count = count;
return stack;
}
}
void ServerInventoryList::setDirty() {
void ServerInventoryList::manipulated(){
dirty = true;
}
unsigned short ServerInventoryList::getLength() {
return itemstacks.size();
}
unsigned short ServerInventoryList::getWidth() {
return width;
}
std::string ServerInventoryList::getName() {
return name;
}
bool ServerInventoryList::addWatcher(unsigned int cid) {
auto& client = clients->getClient(cid);
if (!client) return false;
@ -261,8 +45,9 @@ bool ServerInventoryList::removeWatcher(unsigned int cid) {
Packet ServerInventoryList::createPacket() {
Serializer s{};
s.append<std::string>(invName)
.append<std::string>(name)
.append<std::string>(listName)
.append<unsigned int>(itemstacks.size())
.append<unsigned int>(width);

View File

@ -5,42 +5,17 @@
#pragma once
#include <list>
#include <vector>
#include <functional>
#include "ItemStack.h"
#include "InventoryList.h"
class ClientList;
class ServerClient;
class Packet;
class ServerInventoryList {
class ServerInventoryList : public InventoryList {
public:
enum class Callback { ALLOW_TAKE, ALLOW_PUT, ON_TAKE, ON_PUT };
ServerInventoryList(DefinitionAtlas& defs, ClientList* list, const std::string& invName,
const std::string& name, unsigned short size, unsigned short width);
unsigned short getLength();
unsigned short getWidth();
std::string getName();
// Place the stack at i into the existing stack, returning overflow or other stack.
ItemStack placeStack(unsigned short i, const ItemStack& stack, bool playerInitiated = false);
// Split the stack at i and return half of it, rounded up
ItemStack splitStack(unsigned short i, bool playerInitiated = false);
// Adds as much of `stack` to the inventory as possible, returns leftover.
ItemStack addStack(ItemStack stack, bool playerInitiated = false);
// Returns how many of `stack`'s items fit, from 0 to stack.count.
unsigned short stackFits(const ItemStack& stack);
// Attempts to remove the usertype and amount of items specified by `stack`. Returns actual ItemStack of what was removed.
ItemStack takeStack(ItemStack request, bool playerInitiated = false);
void setStack(unsigned short i, const ItemStack& stack);
ItemStack getStack(unsigned short i);
// Removes up to count items from ind, returns the items removed
ItemStack removeStack(unsigned short ind, unsigned short count);
const std::string& listName, unsigned short size, unsigned short width);
bool addWatcher(unsigned int cid);
bool removeWatcher(unsigned int cid);
@ -48,22 +23,13 @@ public:
void sendAll();
void sendTo(std::shared_ptr<ServerClient> client);
void setLuaCallback(Callback type, sol::function cb);
sol::function getLuaCallback(Callback type);
DefinitionAtlas& defs;
bool dirty = false;
private:
void setDirty();
void manipulated() override;
Packet createPacket();
std::vector<ItemStack> itemstacks {};
unsigned short width = 0;
std::string name;
std::string invName;
std::array<sol::function, 4> luaCallbacks = {};
ClientList* clients;
std::list<unsigned int> watchers;
};