Server-side inventory functionality! **yay**

master
Nicole Collings 2020-03-01 14:33:47 -08:00
parent 26e770b1bd
commit 8bd2e404cd
21 changed files with 145 additions and 61 deletions

View File

@ -90,7 +90,7 @@ void GuiInventoryList::leftClick(bool down, glm::ivec2 pos) {
if (index < 0 || index >= list->getLength()) return;
hand->setStack(0, list->placeStack(index, hand->getStack(0), true));
list->primaryInteract(*hand, index);
}
void GuiInventoryList::rightClick(bool down, glm::ivec2 pos) {
@ -105,24 +105,7 @@ void GuiInventoryList::rightClick(bool down, glm::ivec2 pos) {
unsigned short index = slot.x + slot.y * list->getWidth();
if (index >= list->getLength()) return;
auto handStack = hand->getStack(0);
if (handStack.count == 0) {
hand->setStack(0, list->splitStack(index, true));
}
else {
auto handStack = hand->getStack(0);
auto listStack = list->getStack(index);
if (listStack.id == 0 || listStack.id == handStack.id) {
auto overflow = list->placeStack(index, {handStack.id, 1}, true);
handStack.count -= 1;
if (handStack.count == 0) handStack.id = 0;
if (overflow.count != 0) handStack.count += overflow.count;
hand->setStack(0, handStack);
}
else {
hand->setStack(0, list->placeStack(index, hand->getStack(0), true));
}
}
list->secondaryInteract(*hand, index);
}
void GuiInventoryList::drawContents() {

View File

@ -203,6 +203,30 @@ ItemStack InventoryList::removeStack(unsigned short ind, unsigned short count) {
}
}
void InventoryList::primaryInteract(InventoryList& hand, unsigned short ind) {
hand.setStack(0, placeStack(ind, hand.getStack(0), true));
}
void InventoryList::secondaryInteract(InventoryList &hand, unsigned short ind) {
auto handStack = hand.getStack(0);
if (handStack.count == 0) {
hand.setStack(0, splitStack(ind, true));
}
else {
auto listStack = getStack(ind);
if (listStack.id == 0 || listStack.id == handStack.id) {
auto overflow = placeStack(ind, {handStack.id, 1}, true);
handStack.count -= 1;
if (handStack.count == 0) handStack.id = 0;
if (overflow.count != 0) handStack.count += overflow.count;
hand.setStack(0, handStack);
}
else {
hand.setStack(0, placeStack(ind, hand.getStack(0), true));
}
}
}
ItemStack InventoryList::getStack(unsigned short i) const {
return itemstacks[i];
}

View File

@ -39,6 +39,11 @@ public:
// Removes up to count items from ind, returns the items removed
virtual ItemStack removeStack(unsigned short ind, unsigned short count);
// Primary interaction - The action performed when left clicking an inventory slot.
virtual void primaryInteract(InventoryList& hand, unsigned short ind);
// Secondary interaction - The action performed when right clicking an inventory slot.
virtual void secondaryInteract(InventoryList& hand, unsigned short ind);
ItemStack getStack(unsigned short i) const;
void setStack(unsigned short i, const ItemStack& stack);

View File

@ -44,3 +44,13 @@ bool InventoryRefs::removeWatcher(const std::string &inv, const std::string &lis
inventories[inv]->operator[](list)->removeWatcher(cid);
return true;
}
void InventoryRefs::primaryInteract(const std::string &inv, const std::string &list, unsigned short ind, unsigned int cid) {
std::cout << "primary interaction" << std::endl;
inventories[inv]->operator[](list)->primaryInteract(*inventories["player:" + std::to_string(cid)]->operator[]("hand"), ind);
}
void InventoryRefs::secondaryInteract(const std::string &inv, const std::string &list, unsigned short ind, unsigned int cid) {
std::cout << "secondary interaction" << std::endl;
inventories[inv]->operator[](list)->secondaryInteract(*inventories["player:" + std::to_string(cid)]->operator[]("hand"), ind);
}

View File

@ -21,6 +21,9 @@ public:
bool addWatcher(const std::string& inv, const std::string& list, unsigned int cid);
bool removeWatcher(const std::string& inv, const std::string& list, unsigned int cid);
void primaryInteract(const std::string& inv, const std::string& list, unsigned short ind, unsigned int cid);
void secondaryInteract(const std::string& inv, const std::string& list, unsigned short ind, unsigned int cid);
private:
std::unordered_map<std::string, std::shared_ptr<Inventory>> inventories {};

View File

@ -5,7 +5,11 @@
#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, this->name, name, length, width)}});
namespace ph = std::placeholders;
lists.insert({name, {(maintain ? -1 : 0),
std::make_shared<LocalInventoryList>(defs, this->name, name, length, width,
std::bind(primaryCallback, this->name, name, ph::_1), std::bind(secondaryCallback, this->name, name, ph::_1))}});
}
std::shared_ptr<LocalInventoryList> LocalInventory::operator[](std::string name) {

View File

@ -11,7 +11,11 @@
class LocalInventory {
public:
LocalInventory(DefinitionAtlas& defs, const std::string& name) : defs(defs), name(name) {};
typedef std::function<void(const std::string& inv, const std::string& list, unsigned short)> inv_callback_fn;
LocalInventory(DefinitionAtlas& defs, const std::string& name,
inv_callback_fn primaryCallback, inv_callback_fn secondaryCallback) :
defs(defs), name(name), primaryCallback(primaryCallback), secondaryCallback(secondaryCallback) {};
void createList(std::string name, unsigned short length, unsigned short width, bool maintain = false);
std::shared_ptr<LocalInventoryList> operator[](std::string name);
@ -22,4 +26,7 @@ public:
private:
std::string name;
std::unordered_map<std::string, std::pair<double, std::shared_ptr<LocalInventoryList>>> lists;
inv_callback_fn primaryCallback;
inv_callback_fn secondaryCallback;
};

View File

@ -5,8 +5,22 @@
#include "LocalInventoryList.h"
LocalInventoryList::LocalInventoryList(DefinitionAtlas& defs, const std::string& invName,
const std::string& listName, unsigned short size, unsigned short width) :
InventoryList(defs, invName, listName, size, width) {}
const std::string& listName, unsigned short size, unsigned short width,
std::function<void(unsigned short)> primaryCallback, std::function<void(unsigned short)> secondaryCallback) :
InventoryList(defs, invName, listName, size, width),
primaryCallback(primaryCallback),
secondaryCallback(secondaryCallback) {}
void LocalInventoryList::primaryInteract(InventoryList &hand, unsigned short ind) {
InventoryList::primaryInteract(hand, ind);
primaryCallback(ind);
}
void LocalInventoryList::secondaryInteract(InventoryList &hand, unsigned short ind) {
InventoryList::secondaryInteract(hand, ind);
secondaryCallback(ind);
}
void LocalInventoryList::setData(unsigned int size, unsigned int width, std::vector<ItemStack> stacks) {
this->width = width;
@ -18,7 +32,6 @@ void LocalInventoryList::setGuiCallback(std::function<void()> cb) {
this->guiCallback = cb;
}
void LocalInventoryList::manipulated(){
void LocalInventoryList::manipulated() {
if (guiCallback != nullptr) guiCallback();
}
}

View File

@ -9,7 +9,11 @@
class LocalInventoryList : public InventoryList {
public:
LocalInventoryList(DefinitionAtlas& defs, const std::string& invName,
const std::string& listName, unsigned short size, unsigned short width);
const std::string& listName, unsigned short size, unsigned short width,
std::function<void(unsigned short)> primaryCallback, std::function<void(unsigned short)> secondaryCallback);
void primaryInteract(InventoryList& hand, unsigned short ind) override;
void secondaryInteract(InventoryList& hand, unsigned short ind) override;
void setData(unsigned int size, unsigned int width, std::vector<ItemStack> stacks);
void setGuiCallback(std::function<void()> cb);
@ -17,4 +21,6 @@ public:
private:
void manipulated() override;
std::function<void()> guiCallback = nullptr;
std::function<void(unsigned short)> primaryCallback = nullptr;
std::function<void(unsigned short)> secondaryCallback = nullptr;
};

View File

@ -6,17 +6,17 @@
#include "../scene/net/ClientNetworkInterpreter.h"
LocalInventoryRefs::LocalInventoryRefs(LocalDefinitionAtlas& defs) :
defs(defs) {
LocalInventoryRefs::LocalInventoryRefs(LocalDefinitionAtlas& defs, ClientNetworkInterpreter& net) : defs(defs) {
namespace ph = std::placeholders;
inventories.insert({"current_player", std::make_shared<LocalInventory>(defs, "current_player")});
this->watchFn = std::bind(&ClientNetworkInterpreter::watchInv, &net, ph::_1, ph::_2);
this->primaryCallback = std::bind(&ClientNetworkInterpreter::primaryInteract, &net, ph::_1, ph::_2, ph::_3);
this->secondaryCallback = std::bind(&ClientNetworkInterpreter::secondaryInteract, &net, ph::_1, ph::_2, ph::_3);
inventories.insert({"current_player", std::make_shared<LocalInventory>(defs, "current_player", primaryCallback, secondaryCallback)});
inventories["current_player"]->createList("hand", 1, 1, true);
}
void LocalInventoryRefs::setWatchFunction(std::function<void(std::string, std::string)> watchFn) {
this->watchFn = watchFn;
}
void LocalInventoryRefs::update(double delta, ClientNetworkInterpreter& net) {
time += delta;

View File

@ -13,9 +13,9 @@
class LocalInventoryRefs {
public:
LocalInventoryRefs(LocalDefinitionAtlas& defs);
typedef std::function<void(const std::string& inv, const std::string& list, unsigned short)> inv_callback_fn;
void setWatchFunction(std::function<void(std::string, std::string)> watchFn);
LocalInventoryRefs(LocalDefinitionAtlas& defs, ClientNetworkInterpreter& net);
void update(double delta, ClientNetworkInterpreter& net);
void packetReceived(std::unique_ptr<Packet> p);
@ -27,6 +27,8 @@ private:
std::unordered_map<std::string, std::shared_ptr<LocalInventory>> inventories {};
std::function<void(std::string, std::string)> watchFn = nullptr;
inv_callback_fn primaryCallback = nullptr;
inv_callback_fn secondaryCallback = nullptr;
LocalDefinitionAtlas& defs;

View File

@ -56,7 +56,7 @@ Packet ServerInventoryList::createPacket() {
s.append<unsigned int>(stack.id);
}
return s.packet(PacketType::INVENTORY, false);
return s.packet(PacketType::INV_DATA, false);
}
void ServerInventoryList::sendTo(std::shared_ptr<ServerClient> client) {

View File

@ -5,9 +5,9 @@
#include "GameScene.h"
GameScene::GameScene(ClientState& state) : Scene(state),
refs(game.defs),
game(state.defs),
world(game, &net),
refs(game.defs, net),
net(state.connection, game, player),
player(world, game, state.renderer, refs),
debugGui(state.renderer.window.getSize(), game) {
@ -21,8 +21,6 @@ GameScene::GameScene(ClientState& state) : Scene(state),
net.init(&world, std::bind(&LocalInventoryRefs::packetReceived, refs, ph::_1));
game.init(world, player);
refs.setWatchFunction(std::bind(&ClientNetworkInterpreter::watchInv, &net, ph::_1, ph::_2));
state.renderer.window.addResizeCallback("gamescene", std::bind(&DebugGui::bufferResized, debugGui, ph::_1));
state.renderer.setClearColor(148, 194, 240);
state.renderer.window.lockMouse(true);

View File

@ -20,8 +20,8 @@ public:
public:
ClientGame& game;
LocalInventoryRefs refs;
ClientNetworkInterpreter net;
LocalInventoryRefs refs;
LocalWorld world;
Player player;

View File

@ -144,7 +144,7 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<Packet> p) {
std::cout << Log::err << "Invalid inventory " << source << ":" << list << " was requested by client." << Log::endl;
exit(1);
}
case PacketType::INVENTORY: {
case PacketType::INV_DATA: {
onInvPacket(std::move(p));
break;
}
@ -158,10 +158,20 @@ void ClientNetworkInterpreter::setBlock(glm::ivec3 pos, unsigned int block) {
void ClientNetworkInterpreter::watchInv(const std::string& inv, const std::string& list) {
Serializer().append(inv).append(list)
.packet(PacketType::WATCH_INV).sendTo(connection.getPeer(), PacketChannel::INVENTORY);
.packet(PacketType::INV_WATCH).sendTo(connection.getPeer(), PacketChannel::INVENTORY);
}
void ClientNetworkInterpreter::unwatchInv(const std::string& inv, const std::string& list) {
Serializer().append(inv).append(list)
.packet(PacketType::UNWATCH_INV).sendTo(connection.getPeer(), PacketChannel::INVENTORY);
}
.packet(PacketType::INV_UNWATCH).sendTo(connection.getPeer(), PacketChannel::INVENTORY);
}
void ClientNetworkInterpreter::primaryInteract(const std::string &inv, const std::string &list, unsigned short ind) {
Serializer().append<unsigned short>(0).append(inv).append(list).append<unsigned short>(ind)
.packet(PacketType::INV_INTERACT).sendTo(connection.getPeer(), PacketChannel::INVENTORY);
}
void ClientNetworkInterpreter::secondaryInteract(const std::string &inv, const std::string &list, unsigned short ind) {
Serializer().append<unsigned short>(1).append(inv).append(list).append<unsigned short>(ind)
.packet(PacketType::INV_INTERACT).sendTo(connection.getPeer(), PacketChannel::INVENTORY);
}

View File

@ -20,6 +20,9 @@ public:
void watchInv(const std::string& inv, const std::string& list);
void unwatchInv(const std::string& inv, const std::string& list);
void primaryInteract(const std::string& inv, const std::string& list, unsigned short ind);
void secondaryInteract(const std::string& inv, const std::string& list, unsigned short ind);
int recvPackets = 0;
int serverSideChunkGens = 0;
private:

View File

@ -155,7 +155,7 @@ void Server::handlePlayerPacket(ServerClient &client, Packet& p) {
}
break;
}
case PacketType::WATCH_INV: {
case PacketType::INV_WATCH: {
Deserializer d(p.data);
std::string source = d.read<std::string>();
@ -173,7 +173,7 @@ void Server::handlePlayerPacket(ServerClient &client, Packet& p) {
break;
}
case PacketType::UNWATCH_INV: {
case PacketType::INV_UNWATCH: {
Deserializer d(p.data);
std::string source = d.read<std::string>();
@ -189,6 +189,23 @@ void Server::handlePlayerPacket(ServerClient &client, Packet& p) {
break;
}
break;
}
case PacketType::INV_INTERACT: {
Deserializer d(p.data);
unsigned short type = d.read<unsigned short>();
std::string source = d.read<std::string>();
std::string list = d.read<std::string>();
unsigned short ind = d.read<unsigned short>();
// TODO: When inventory saving / loading is implemented there will need to be a cross-save identifier.
if (source == "current_player") source = "player:" + std::to_string(client.cid);
if (type == 0) refs.primaryInteract(source, list, ind, client.cid);
else refs.secondaryInteract(source, list, ind, client.cid);
break;
}
}

View File

@ -26,9 +26,10 @@ enum class PacketType {
ENTITY_REMOVED,
// Inventory
WATCH_INV,
UNWATCH_INV,
INV_WATCH,
INV_UNWATCH,
INV_INVALID,
INVENTORY
INV_DATA,
INV_INTERACT
};

View File

@ -17,7 +17,7 @@ zepha.register_keybind("zeus:inventory:open_inventory", {
position: 0px 50px
size: 218px 100px
padding: 20px 10px 8px 10px
background: asset(zeus:inventory:inventory)
background: zeus:inventory:inventory
inventory
source: current_player
@ -31,7 +31,7 @@ zepha.register_keybind("zeus:inventory:open_inventory", {
position: 0px -48px
size: 218px 100px
padding: 20px 10px 8px 10px
background: asset(zeus:inventory:chest)
background: zeus:inventory:chest
inventory
source: current_player

View File

@ -51,15 +51,6 @@ zepha.register_keybind("zeus:inventory:open_inventory", {
position: 41px -8px
size: 34px 52px
overflow: hidden
model
scale: 86 86
position: 15px 52px
type: model
source: zeus:default:player
texture: zeus:default:player
anim_range: 0 300
end
end
end

View File

@ -4,3 +4,10 @@ zepha.register_item("zeus:materials:flint", {
"zeus:materials:flint",
}
})
crafting.register_recipe({
output = "zeus:materials:flint",
recipe = {
{"zeus:default:cobblestone"},
}
})