Server-side inventories can be sent to the client for viewing.
parent
6b4c866ba7
commit
3093d53ea2
|
@ -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)
|
||||
lua/api/class/LocalLuaInventoryList.h game/inventory/InventoryRefs.cpp game/inventory/InventoryRefs.h)
|
||||
|
||||
add_library (Zepha_Core ${ZEPHA_SRC})
|
|
@ -24,4 +24,5 @@ void ClientGame::init(LocalWorld &world, Player& player) {
|
|||
|
||||
void ClientGame::update(double delta, bool* keys) {
|
||||
parser.update(delta, keys);
|
||||
textures.update();
|
||||
}
|
||||
|
|
|
@ -142,6 +142,11 @@ void GuiInventoryList::rightClick(bool down, glm::ivec2 pos) {
|
|||
}
|
||||
|
||||
void GuiInventoryList::drawContents() {
|
||||
this->hitbox = glm::ivec2 {
|
||||
padding.x + list->getWidth() * (innerPadding.x*scale.x),
|
||||
padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y*scale.y)
|
||||
};
|
||||
|
||||
empty();
|
||||
|
||||
auto fontRef = defs->textures["font"];
|
||||
|
|
|
@ -4,8 +4,17 @@
|
|||
|
||||
#include "Inventory.h"
|
||||
|
||||
void Inventory::sendDirtyLists() {
|
||||
for (auto& list : lists) {
|
||||
if (list.second->dirty) {
|
||||
list.second->sendAll();
|
||||
list.second->dirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::createList(std::string name, unsigned short length, unsigned short width) {
|
||||
lists.emplace(name, std::make_shared<InventoryList>(defs, name, length, width));
|
||||
lists.emplace(name, std::make_shared<InventoryList>(defs, clients, this->name, name, length, width));
|
||||
}
|
||||
|
||||
std::shared_ptr<InventoryList> Inventory::operator[](std::string name) {
|
||||
|
@ -15,4 +24,4 @@ std::shared_ptr<InventoryList> Inventory::operator[](std::string name) {
|
|||
|
||||
void Inventory::removeList(std::string name) {
|
||||
lists.erase(name);
|
||||
}
|
||||
}
|
|
@ -9,15 +9,21 @@
|
|||
#include <memory>
|
||||
#include "InventoryList.h"
|
||||
|
||||
class ClientList;
|
||||
|
||||
class Inventory {
|
||||
public:
|
||||
Inventory(DefinitionAtlas& defs) : defs(defs) {};
|
||||
Inventory(DefinitionAtlas& defs, ClientList* clients, const std::string& name) : defs(defs), clients(clients), name(name) {};
|
||||
|
||||
void sendDirtyLists();
|
||||
|
||||
void createList(std::string name, unsigned short length, unsigned short width);
|
||||
std::shared_ptr<InventoryList> operator[](std::string name);
|
||||
void removeList(std::string name);
|
||||
|
||||
DefinitionAtlas& defs;
|
||||
std::string name;
|
||||
private:
|
||||
ClientList* clients;
|
||||
std::map<std::string, std::shared_ptr<InventoryList>> lists;
|
||||
};
|
||||
|
|
|
@ -4,19 +4,21 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "InventoryList.h"
|
||||
|
||||
#include "../../util/net/Packet.h"
|
||||
#include "../../util/net/Serializer.h"
|
||||
#include "../../server/conn/ClientList.h"
|
||||
#include "../../lua/api/class/LuaItemStack.h"
|
||||
|
||||
InventoryList::InventoryList(DefinitionAtlas& defs, const std::string& name, unsigned short size, unsigned short width) :
|
||||
InventoryList::InventoryList(DefinitionAtlas& defs, ClientList* list, const std::string& invName, const std::string& name, unsigned short size, unsigned short width) :
|
||||
defs(defs),
|
||||
name(name),
|
||||
itemstacks(size),
|
||||
width(width) {}
|
||||
|
||||
|
||||
void InventoryList::setGuiCallback(std::function<void()> cb) {
|
||||
this->guiCallback = cb;
|
||||
}
|
||||
width(width),
|
||||
clients(list),
|
||||
invName(invName),
|
||||
itemstacks(size) {}
|
||||
|
||||
void InventoryList::setLuaCallback(InventoryList::Callback type, sol::function cb) {
|
||||
luaCallbacks[static_cast<size_t>(type)] = cb;
|
||||
|
@ -33,7 +35,7 @@ ItemStack InventoryList::getStack(unsigned short i) {
|
|||
void InventoryList::setStack(unsigned short i, const ItemStack &stack) {
|
||||
if (stack != getStack(i)) {
|
||||
itemstacks[i] = stack;
|
||||
triggerCallback();
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +130,7 @@ ItemStack InventoryList::addStack(ItemStack stack, bool playerInitiated) {
|
|||
if (itemstacks[i].count == 0) {
|
||||
if (stack.count <= maxStack) {
|
||||
itemstacks[i] = stack;
|
||||
triggerCallback();
|
||||
setDirty();
|
||||
return ItemStack{};
|
||||
}
|
||||
else {
|
||||
|
@ -141,7 +143,7 @@ ItemStack InventoryList::addStack(ItemStack stack, bool playerInitiated) {
|
|||
unsigned int fits = maxStack - itemstacks[i].count;
|
||||
if (fits >= stack.count) {
|
||||
itemstacks[i].count += stack.count;
|
||||
triggerCallback();
|
||||
setDirty();
|
||||
return ItemStack {};
|
||||
}
|
||||
else {
|
||||
|
@ -152,7 +154,7 @@ ItemStack InventoryList::addStack(ItemStack stack, bool playerInitiated) {
|
|||
i++;
|
||||
}
|
||||
|
||||
triggerCallback();
|
||||
setDirty();
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
@ -190,7 +192,7 @@ ItemStack InventoryList::takeStack(ItemStack request, bool playerInitiated) {
|
|||
unsigned int can_take = itemstacks[i].count;
|
||||
if (can_take >= to_remove) {
|
||||
itemstacks[i].count -= to_remove;
|
||||
triggerCallback();
|
||||
setDirty();
|
||||
return request;
|
||||
}
|
||||
else {
|
||||
|
@ -202,7 +204,7 @@ ItemStack InventoryList::takeStack(ItemStack request, bool playerInitiated) {
|
|||
}
|
||||
|
||||
request.count = (request.count - to_remove);
|
||||
triggerCallback();
|
||||
setDirty();
|
||||
return request;
|
||||
}
|
||||
|
||||
|
@ -220,8 +222,8 @@ ItemStack InventoryList::removeStack(unsigned short ind, unsigned short count) {
|
|||
}
|
||||
}
|
||||
|
||||
void InventoryList::triggerCallback() {
|
||||
if (guiCallback != nullptr) guiCallback();
|
||||
void InventoryList::setDirty() {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
unsigned short InventoryList::getLength() {
|
||||
|
@ -234,4 +236,61 @@ unsigned short InventoryList::getWidth() {
|
|||
|
||||
std::string InventoryList::getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
bool InventoryList::addWatcher(unsigned int cid) {
|
||||
auto& client = clients->getClient(cid);
|
||||
if (!client) return false;
|
||||
|
||||
for (const auto& i : watchers) if (i == cid) return false;
|
||||
watchers.push_back(cid);
|
||||
|
||||
sendTo(client);
|
||||
}
|
||||
|
||||
bool InventoryList::removeWatcher(unsigned int cid) {
|
||||
for (auto it = watchers.cbegin(); it != watchers.cend();) {
|
||||
if (*it == cid) {
|
||||
watchers.erase(it);
|
||||
return true;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Packet InventoryList::createPacket() {
|
||||
Serializer s{};
|
||||
s.append<std::string>(invName)
|
||||
.append<std::string>(name)
|
||||
.append<unsigned int>(itemstacks.size())
|
||||
.append<unsigned int>(width);
|
||||
|
||||
for (auto& stack : itemstacks) {
|
||||
s.append<unsigned short>(stack.count);
|
||||
s.append<unsigned int>(stack.id);
|
||||
}
|
||||
|
||||
return s.packet(PacketType::INVENTORY, false);
|
||||
}
|
||||
|
||||
void InventoryList::sendTo(std::shared_ptr<ServerClient> client) {
|
||||
if (!client) return;
|
||||
auto p = createPacket();
|
||||
p.sendTo(client->peer, PacketChannel::INVENTORY);
|
||||
}
|
||||
|
||||
void InventoryList::sendAll() {
|
||||
auto p = createPacket();
|
||||
|
||||
for (auto it = watchers.cbegin(); it != watchers.cend();) {
|
||||
auto& client = clients->getClient(*it);
|
||||
if (!client) {
|
||||
it = watchers.erase(it);
|
||||
}
|
||||
else {
|
||||
p.sendTo(client->peer, PacketChannel::INVENTORY);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,19 @@
|
|||
#include <list>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
#include "ItemStack.h"
|
||||
|
||||
class ClientList;
|
||||
class ServerClient;
|
||||
class Packet;
|
||||
|
||||
class InventoryList {
|
||||
public:
|
||||
enum class Callback { ALLOW_TAKE, ALLOW_PUT, ON_TAKE, ON_PUT };
|
||||
|
||||
InventoryList(DefinitionAtlas& defs, const std::string& name, unsigned short size, unsigned short width);
|
||||
InventoryList(DefinitionAtlas& defs, ClientList* list, const std::string& invName,
|
||||
const std::string& name, unsigned short size, unsigned short width);
|
||||
|
||||
unsigned short getLength();
|
||||
unsigned short getWidth();
|
||||
|
@ -36,19 +42,28 @@ public:
|
|||
// 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);
|
||||
bool addWatcher(unsigned int cid);
|
||||
bool removeWatcher(unsigned int cid);
|
||||
|
||||
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 triggerCallback();
|
||||
void setDirty();
|
||||
Packet createPacket();
|
||||
|
||||
std::vector<ItemStack> itemstacks {};
|
||||
unsigned short width = 0;
|
||||
std::string name;
|
||||
std::string invName;
|
||||
|
||||
std::function<void()> guiCallback = nullptr;
|
||||
std::array<sol::function, 4> luaCallbacks = {};
|
||||
|
||||
ClientList* clients;
|
||||
std::list<unsigned int> watchers;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// Created by aurailus on 2020-02-26.
|
||||
//
|
||||
|
||||
#include "InventoryRefs.h"
|
||||
|
||||
#include "InventoryList.h"
|
||||
|
||||
InventoryRefs::InventoryRefs(ServerDefinitionAtlas &defs, ClientList* clients) :
|
||||
defs(defs), clients(clients) {}
|
||||
|
||||
void InventoryRefs::update() {
|
||||
for (auto& inv : inventories) {
|
||||
inv.second->sendDirtyLists();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> InventoryRefs::createInv(const std::string &inv) {
|
||||
inventories.emplace(inv, std::make_shared<Inventory>(defs, clients, inv));
|
||||
return inventories[inv];
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> InventoryRefs::getInv(const std::string &inv) {
|
||||
return inventories[inv];
|
||||
}
|
||||
|
||||
std::shared_ptr<InventoryList> InventoryRefs::getList(const std::string &inv, const std::string &list) {
|
||||
if (!inventories.count(inv)) return nullptr;
|
||||
return inventories[inv]->operator[](list);
|
||||
}
|
||||
|
||||
bool InventoryRefs::addWatcher(const std::string &inv, const std::string &list, unsigned int cid) {
|
||||
if (!inventories.count(inv)) return false;
|
||||
if (!inventories[inv]->operator[](list)) return false;
|
||||
|
||||
inventories[inv]->operator[](list)->addWatcher(cid);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InventoryRefs::removeWatcher(const std::string &inv, const std::string &list, unsigned int cid) {
|
||||
if (!inventories.count(inv)) return false;
|
||||
if (!inventories[inv]->operator[](list)) return false;
|
||||
|
||||
inventories[inv]->operator[](list)->removeWatcher(cid);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Created by aurailus on 2020-02-26.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../def/ServerDefinitionAtlas.h"
|
||||
#include "Inventory.h"
|
||||
|
||||
class InventoryList;
|
||||
|
||||
class InventoryRefs {
|
||||
public:
|
||||
InventoryRefs(ServerDefinitionAtlas& defs, ClientList* clients);
|
||||
|
||||
void update();
|
||||
|
||||
std::shared_ptr<Inventory> createInv(const std::string& inv);
|
||||
std::shared_ptr<Inventory> getInv(const std::string& inv);
|
||||
std::shared_ptr<InventoryList> getList(const std::string& inv, const std::string& list);
|
||||
|
||||
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);
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<Inventory>> inventories {};
|
||||
|
||||
ClientList* clients;
|
||||
ServerDefinitionAtlas& defs;
|
||||
double time = 0;
|
||||
};
|
|
@ -15,6 +15,11 @@ LocalInventoryList::LocalInventoryList(DefinitionAtlas& defs, const std::string&
|
|||
itemstacks(size),
|
||||
width(width) {}
|
||||
|
||||
void LocalInventoryList::setData(unsigned int size, unsigned int width, std::vector<ItemStack> stacks) {
|
||||
this->width = width;
|
||||
this->itemstacks = stacks;
|
||||
triggerCallback();
|
||||
}
|
||||
|
||||
void LocalInventoryList::setGuiCallback(std::function<void()> cb) {
|
||||
this->guiCallback = cb;
|
||||
|
@ -236,4 +241,4 @@ unsigned short LocalInventoryList::getWidth() {
|
|||
|
||||
std::string LocalInventoryList::getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ public:
|
|||
unsigned short getWidth();
|
||||
std::string getName();
|
||||
|
||||
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
|
||||
|
|
|
@ -4,15 +4,20 @@
|
|||
|
||||
#include "LocalInventoryRefs.h"
|
||||
|
||||
LocalInventoryRefs::LocalInventoryRefs(LocalDefinitionAtlas& defs, ClientNetworkInterpreter& net) :
|
||||
defs(defs),
|
||||
net(net) {
|
||||
#include "../scene/net/ClientNetworkInterpreter.h"
|
||||
|
||||
LocalInventoryRefs::LocalInventoryRefs(LocalDefinitionAtlas& defs) :
|
||||
defs(defs) {
|
||||
|
||||
inventories.insert({"current_player", std::make_shared<LocalInventory>(defs, "current_player")});
|
||||
inventories["current_player"]->createList("hand", 1, 1, true);
|
||||
}
|
||||
|
||||
void LocalInventoryRefs::update(double delta) {
|
||||
void LocalInventoryRefs::setWatchFunction(std::function<void(std::string, std::string)> watchFn) {
|
||||
this->watchFn = watchFn;
|
||||
}
|
||||
|
||||
void LocalInventoryRefs::update(double delta, ClientNetworkInterpreter& net) {
|
||||
time += delta;
|
||||
|
||||
for (auto mIt = inventories.begin(); mIt != inventories.end();) {
|
||||
|
@ -29,11 +34,36 @@ std::shared_ptr<LocalInventoryList> LocalInventoryRefs::getList(const std::strin
|
|||
if (!inventories.count(inv)) inventories.insert({inv, {}});
|
||||
if (inventories[inv]->operator[](list) == nullptr) {
|
||||
inventories[inv]->createList(list, 1, 1);
|
||||
net.watchInv(inv, list);
|
||||
watchFn(inv, list);
|
||||
}
|
||||
return inventories[inv]->operator[](list);
|
||||
}
|
||||
|
||||
std::shared_ptr<LocalInventoryList> LocalInventoryRefs::getHand() {
|
||||
return inventories["current_player"]->operator[]("hand");
|
||||
}
|
||||
|
||||
void LocalInventoryRefs::packetReceived(std::unique_ptr<Packet> p) {
|
||||
Deserializer d(p->data);
|
||||
|
||||
std::string source = d.read<std::string>();
|
||||
std::string list = d.read<std::string>();
|
||||
if (strncmp(source.data(), "player:", 7) == 0) source = "current_player";
|
||||
|
||||
if (!inventories.count(source)) return;
|
||||
if (!inventories[source]->operator[](list)) return;
|
||||
|
||||
unsigned int size = d.read<unsigned int>();
|
||||
unsigned int width = d.read<unsigned int>();
|
||||
|
||||
std::vector<ItemStack> stacks {};
|
||||
stacks.reserve(size);
|
||||
|
||||
while (!d.atEnd()) {
|
||||
unsigned short count = d.read<unsigned short>();
|
||||
unsigned int id = d.read<unsigned int>();
|
||||
stacks.push_back({id, count});
|
||||
}
|
||||
|
||||
inventories[source]->operator[](list)->setData(size, width, stacks);
|
||||
}
|
|
@ -9,14 +9,16 @@
|
|||
|
||||
#include "LocalInventory.h"
|
||||
#include "LocalInventoryList.h"
|
||||
#include "../scene/net/ClientNetworkInterpreter.h"
|
||||
#include "../../def/LocalDefinitionAtlas.h"
|
||||
|
||||
class LocalInventoryRefs {
|
||||
public:
|
||||
LocalInventoryRefs(LocalDefinitionAtlas& defs, ClientNetworkInterpreter& net);
|
||||
LocalInventoryRefs(LocalDefinitionAtlas& defs);
|
||||
|
||||
void update(double delta);
|
||||
void setWatchFunction(std::function<void(std::string, std::string)> watchFn);
|
||||
|
||||
void update(double delta, ClientNetworkInterpreter& net);
|
||||
void packetReceived(std::unique_ptr<Packet> p);
|
||||
|
||||
std::shared_ptr<LocalInventory> getInv(const std::string& inv);
|
||||
std::shared_ptr<LocalInventoryList> getList(const std::string& inv, const std::string& list);
|
||||
|
@ -24,7 +26,8 @@ public:
|
|||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<LocalInventory>> inventories {};
|
||||
|
||||
ClientNetworkInterpreter& net;
|
||||
std::function<void(std::string, std::string)> watchFn = nullptr;
|
||||
|
||||
LocalDefinitionAtlas& defs;
|
||||
|
||||
double time = 0;
|
||||
|
|
|
@ -5,48 +5,43 @@
|
|||
#include "GameScene.h"
|
||||
|
||||
GameScene::GameScene(ClientState& state) : Scene(state),
|
||||
refs(game.defs),
|
||||
game(state.defs),
|
||||
refs(game.defs, net),
|
||||
world(game, &playerPos, &net),
|
||||
world(game, &net),
|
||||
net(state.connection, game, player),
|
||||
player(world, game, state.renderer, refs),
|
||||
debugGui(state.renderer.window.getSize(), game) {
|
||||
|
||||
state.renderer.setClearColor(148, 194, 240);
|
||||
state.renderer.window.lockMouse(true);
|
||||
|
||||
game.init(world, player);
|
||||
world.init();
|
||||
net.init(&world);
|
||||
namespace ph = std::placeholders;
|
||||
|
||||
Packet r(PacketType::CONNECT_DATA_RECVD);
|
||||
r.sendTo(state.connection.getPeer(), PacketChannel::CONNECT);
|
||||
|
||||
state.renderer.window.addResizeCallback("gamescene", [&](glm::ivec2 win) {
|
||||
debugGui.bufferResized(win);
|
||||
});
|
||||
world.init(&player);
|
||||
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);
|
||||
}
|
||||
|
||||
void GameScene::update() {
|
||||
game.update(state.delta, state.renderer.window.keys);
|
||||
game.textures.update();
|
||||
refs.update(state.delta);
|
||||
net.update();
|
||||
|
||||
Window& window = state.renderer.window;
|
||||
|
||||
//Update Player
|
||||
player.update(window.input, state.delta, window.getDelta());
|
||||
playerPos = player.getPos();
|
||||
game .update(state.delta, state.renderer.window.keys);
|
||||
refs .update(state.delta, net);
|
||||
net .update();
|
||||
|
||||
for (auto entity : entities) entity->update(state.delta);
|
||||
|
||||
for (auto &chunkPacket : net.chunkPackets) world.loadChunkPacket(std::move(chunkPacket));
|
||||
net.chunkPackets.clear();
|
||||
|
||||
debugGui.update(player, world, game, state.fps, world.getMeshChunkCount(), drawCalls, net.serverSideChunkGens, net.recvPackets);
|
||||
net.recvPackets = 0;
|
||||
world.update(state.delta);
|
||||
net.serverSideChunkGens = 0;
|
||||
net.recvPackets = 0;
|
||||
|
||||
if (window.input.isKeyPressed(GLFW_KEY_F1)) {
|
||||
hudVisible = !hudVisible;
|
||||
|
|
|
@ -20,16 +20,13 @@ public:
|
|||
public:
|
||||
ClientGame& game;
|
||||
|
||||
ClientNetworkInterpreter net;
|
||||
LocalInventoryRefs refs;
|
||||
ClientNetworkInterpreter net;
|
||||
LocalWorld world;
|
||||
|
||||
glm::vec3 playerPos;
|
||||
Player player;
|
||||
|
||||
std::vector<Drawable*> entities;
|
||||
DebugGui debugGui;
|
||||
|
||||
std::vector<Drawable*> entities;
|
||||
int drawCalls = 0;
|
||||
|
||||
bool debugVisible = true;
|
||||
|
|
|
@ -9,16 +9,15 @@
|
|||
#include "../../../util/net/NetHandler.h"
|
||||
|
||||
ClientNetworkInterpreter::ClientNetworkInterpreter(ServerConnection &connection, ClientGame &defs, Player& player) :
|
||||
world(nullptr),
|
||||
player(player),
|
||||
connection(connection),
|
||||
playerModel(std::make_shared<Model>()) {
|
||||
|
||||
playerModel->fromSerialized(defs.models.models["zeus:default:player"], {defs.textures["zeus:default:player"]});
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::init(LocalWorld *world) {
|
||||
void ClientNetworkInterpreter::init(LocalWorld *world, std::function<void(std::unique_ptr<Packet>)> invCallback) {
|
||||
this->world = world;
|
||||
this->onInvPacket = invCallback;
|
||||
}
|
||||
|
||||
void ClientNetworkInterpreter::update() {
|
||||
|
@ -76,7 +75,7 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<Packet> p) {
|
|||
while (!d.atEnd()) {
|
||||
switch (d.read<unsigned int>()) {
|
||||
case static_cast<unsigned int>(NetPlayerField::ID): {
|
||||
id = d.read<unsigned int>();
|
||||
cid = d.read<unsigned int>();
|
||||
break;
|
||||
}
|
||||
case static_cast<unsigned int>(NetPlayerField::POSITION): {
|
||||
|
@ -99,7 +98,7 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<Packet> p) {
|
|||
|
||||
case PacketType::PLAYER_INFO: {
|
||||
unsigned int cid = d.read<unsigned int>();
|
||||
if (cid == id) break;
|
||||
if (this->cid == cid) break;
|
||||
|
||||
bool found = false;
|
||||
for (auto& entity : world->dimension.playerEntities) {
|
||||
|
@ -133,7 +132,7 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<Packet> p) {
|
|||
}
|
||||
|
||||
case PacketType::CHUNK: {
|
||||
chunkPackets.push_back(std::move(p));
|
||||
world->loadChunkPacket(std::move(p));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -141,6 +140,19 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<Packet> p) {
|
|||
serverSideChunkGens = d.read<unsigned int>();
|
||||
break;
|
||||
}
|
||||
|
||||
case PacketType::INV_INVALID: {
|
||||
std::string source = d.read<std::string>();
|
||||
std::string list = d.read<std::string>();
|
||||
|
||||
std::cout << Log::err << "Invalid inventory " << source << ":" << list << " was requested by client." << Log::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
case PacketType::INVENTORY: {
|
||||
onInvPacket(std::move(p));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,8 +169,4 @@ void ClientNetworkInterpreter::watchInv(const std::string& inv, const std::strin
|
|||
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);
|
||||
}
|
||||
|
||||
ClientNetworkInterpreter::~ClientNetworkInterpreter() {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
|
@ -12,27 +12,26 @@ public:
|
|||
ClientNetworkInterpreter(ServerConnection& connection, ClientGame& defs, Player& player);
|
||||
ClientNetworkInterpreter(const ClientNetworkInterpreter& other) = default;
|
||||
|
||||
void init(LocalWorld* world);
|
||||
void init(LocalWorld* world, std::function<void(std::unique_ptr<Packet>)> invCallback);
|
||||
void update();
|
||||
|
||||
void receivedPacket(std::unique_ptr<Packet> ePacket);
|
||||
|
||||
// Functions to be called by outside of ClientNetworkInterpreter
|
||||
void setBlock(glm::ivec3 pos, unsigned int block);
|
||||
void watchInv(const std::string& inv, const std::string& list);
|
||||
void unwatchInv(const std::string& inv, const std::string& list);
|
||||
|
||||
~ClientNetworkInterpreter();
|
||||
|
||||
int recvPackets = 0;
|
||||
int serverSideChunkGens = 0;
|
||||
std::vector<std::unique_ptr<Packet>> chunkPackets;
|
||||
private:
|
||||
void receivedPacket(std::unique_ptr<Packet> ePacket);
|
||||
|
||||
int cid = 0;
|
||||
Player& player;
|
||||
ServerConnection& connection;
|
||||
|
||||
LocalWorld* world = nullptr;
|
||||
std::shared_ptr<Model> playerModel;
|
||||
|
||||
int id = 0;
|
||||
std::function<void(std::unique_ptr<Packet>)> onInvPacket;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,18 +4,19 @@
|
|||
|
||||
#include "LocalWorld.h"
|
||||
|
||||
#include "Player.h"
|
||||
#include "WorldInterpolationStream.h"
|
||||
#include "../net/ClientNetworkInterpreter.h"
|
||||
#include "../../entity/engine/BlockCrackEntity.h"
|
||||
#include "../../entity/engine/ParticleEntity.h"
|
||||
|
||||
LocalWorld::LocalWorld(ClientGame& defs, glm::vec3* playerPos, ClientNetworkInterpreter* server) :
|
||||
dimension(defs),
|
||||
defs(defs),
|
||||
server(server),
|
||||
playerPos(playerPos) {}
|
||||
LocalWorld::LocalWorld(ClientGame& defs, ClientNetworkInterpreter* server) :
|
||||
defs(defs),
|
||||
net(server),
|
||||
dimension(defs) {}
|
||||
|
||||
void LocalWorld::init() {
|
||||
void LocalWorld::init(Player* player) {
|
||||
this->player = player;
|
||||
delete worldGenStream;
|
||||
worldGenStream = new WorldInterpolationStream(55, defs);
|
||||
}
|
||||
|
@ -23,12 +24,12 @@ void LocalWorld::init() {
|
|||
void LocalWorld::update(double delta) {
|
||||
finishChunks();
|
||||
updateBlockDamages(delta);
|
||||
dimension.update(delta, *playerPos);
|
||||
dimension.update(delta, player->getPos());
|
||||
lastMeshUpdates = dimension.lastMeshUpdates;
|
||||
|
||||
auto end = particles.begin();
|
||||
for (auto i = particles.begin(); i < particles.end(); i++) {
|
||||
(*i)->update(delta, *playerPos);
|
||||
(*i)->update(delta, player->getPos());
|
||||
if ((*i)->time > 1) {
|
||||
end = i;
|
||||
delete (*i);
|
||||
|
@ -67,7 +68,7 @@ void LocalWorld::localSetBlock(glm::ivec3 pos, unsigned int block) {
|
|||
}
|
||||
}
|
||||
|
||||
server->setBlock(pos, block);
|
||||
net->setBlock(pos, block);
|
||||
dimension.setBlock(pos, block);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,13 @@ class WorldInterpolationStream;
|
|||
class BlockCrackEntity;
|
||||
class ParticleEntity;
|
||||
class Renderer;
|
||||
class Player;
|
||||
|
||||
class LocalWorld : public World {
|
||||
public:
|
||||
LocalWorld(ClientGame& defs, glm::vec3* playerPos, ClientNetworkInterpreter* server);
|
||||
LocalWorld(ClientGame& defs, ClientNetworkInterpreter* net);
|
||||
|
||||
void init();
|
||||
void init(Player* player);
|
||||
void update(double delta) override;
|
||||
|
||||
void loadChunkPacket(std::unique_ptr<Packet> p);
|
||||
|
@ -47,11 +48,10 @@ private:
|
|||
void finishChunks();
|
||||
void updateBlockDamages(double delta);
|
||||
|
||||
glm::vec3* playerPos;
|
||||
|
||||
std::vector<BlockCrackEntity*> crackedBlocks;
|
||||
std::vector<ParticleEntity*> particles;
|
||||
|
||||
ClientNetworkInterpreter* server = nullptr;
|
||||
Player* player = nullptr;
|
||||
ClientNetworkInterpreter* net = nullptr;
|
||||
WorldInterpolationStream* worldGenStream = nullptr;
|
||||
};
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../../inventory/Inventory.h"
|
||||
#include "../../hud/GameGui.h"
|
||||
#include "../../entity/Collidable.h"
|
||||
#include "../../hud/GameGuiBuilder.h"
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <glm/vec3.hpp>
|
||||
#include "../../../world/Dimension.h"
|
||||
|
||||
class World {
|
||||
public:
|
||||
|
|
|
@ -65,5 +65,5 @@ std::string ServerLuaPlayer::get_address() {
|
|||
}
|
||||
|
||||
ServerLuaInventory ServerLuaPlayer::get_inventory() {
|
||||
return ServerLuaInventory(player.getInventory());
|
||||
return ServerLuaInventory(*player.getInventory());
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ Server::Server(unsigned short port, const std::string& subgame) :
|
|||
defs(subgame),
|
||||
clientList(defs),
|
||||
handler(port, 32),
|
||||
refs(defs.defs, &clientList),
|
||||
world(10, defs, clientList) {
|
||||
|
||||
defs.init(world);
|
||||
|
@ -30,6 +31,7 @@ void Server::update() {
|
|||
|
||||
world.update(0);
|
||||
defs.update(deltaTime, clientList);
|
||||
refs.update();
|
||||
|
||||
ENetEvent event;
|
||||
while (handler.update(&event) && loop.elapsedNs() < interval_ns) {
|
||||
|
@ -40,7 +42,7 @@ void Server::update() {
|
|||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_CONNECT: {
|
||||
clientList.handleConnect(event);
|
||||
clientList.handleConnect(event, refs);
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_DISCONNECT: {
|
||||
|
@ -142,19 +144,37 @@ void Server::handlePlayerPacket(ServerClient &client, Packet& p) {
|
|||
case PacketType::WATCH_INV: {
|
||||
Deserializer d(p.data);
|
||||
|
||||
// std::string source = d.read<std::string>();
|
||||
// std::string list = d.read<std::string>();
|
||||
std::string source = d.read<std::string>();
|
||||
std::string list = d.read<std::string>();
|
||||
|
||||
// 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);
|
||||
|
||||
bool exists = refs.addWatcher(source, list, client.cid);
|
||||
if (!exists) {
|
||||
Serializer().append(source).append(list)
|
||||
.packet(PacketType::INV_INVALID).sendTo(client.peer, PacketChannel::INVENTORY);
|
||||
break;
|
||||
}
|
||||
|
||||
// std::cout << "watching " << source << ":" << list << std::endl;
|
||||
break;
|
||||
}
|
||||
case PacketType::UNWATCH_INV: {
|
||||
Deserializer d(p.data);
|
||||
|
||||
// std::string source = d.read<std::string>();
|
||||
// std::string list = d.read<std::string>();
|
||||
std::string source = d.read<std::string>();
|
||||
std::string list = d.read<std::string>();
|
||||
|
||||
// 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);
|
||||
|
||||
bool exists = refs.removeWatcher(source, list, client.cid);
|
||||
if (!exists) {
|
||||
Serializer().append(source).append(list)
|
||||
.packet(PacketType::INV_INVALID).sendTo(client.peer, PacketChannel::INVENTORY);
|
||||
break;
|
||||
}
|
||||
|
||||
// std::cout << "unwatching " << source << ":" << list << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "config/ServerConfig.h"
|
||||
#include "../def/ServerGame.h"
|
||||
#include "../util/net/NetHandler.h"
|
||||
#include "../game/inventory/InventoryRefs.h"
|
||||
|
||||
class ServerClient;
|
||||
class Packet;
|
||||
|
@ -31,6 +32,7 @@ private:
|
|||
NetHandler handler;
|
||||
ClientList clientList;
|
||||
ServerConfig config;
|
||||
InventoryRefs refs;
|
||||
|
||||
std::unordered_set<unsigned int> playersUpdated {};
|
||||
|
||||
|
|
|
@ -3,20 +3,20 @@
|
|||
//
|
||||
|
||||
#include "ClientList.h"
|
||||
|
||||
#include "../../def/ServerGame.h"
|
||||
#include "../../util/net/Serializer.h"
|
||||
#include "../../util/net/NetHandler.h"
|
||||
#include "../../def/ServerGame.h"
|
||||
#include "../../game/scene/net/NetPlayerField.h"
|
||||
|
||||
|
||||
ClientList::ClientList(ServerGame& defs) :
|
||||
defs(defs) {}
|
||||
|
||||
void ClientList::handleConnect(ENetEvent e) {
|
||||
void ClientList::handleConnect(ENetEvent e, InventoryRefs& refs) {
|
||||
ENetPeer* peer = e.peer;
|
||||
ENetAddress& addr = peer->address;
|
||||
|
||||
auto client = std::make_shared<ServerClient>(peer, addr, defs.defs);
|
||||
auto client = std::make_shared<ServerClient>(peer, addr, defs.defs, refs);
|
||||
clients.push_back(client);
|
||||
peer->data = client.get();
|
||||
|
||||
|
@ -42,6 +42,8 @@ void ClientList::createPlayer(std::shared_ptr<ServerClient> c) {
|
|||
c->hasPlayer = true;
|
||||
c->setUsername("TEMPORaRY");
|
||||
|
||||
c->getInventory()->createList("hand", 1, 1);
|
||||
|
||||
defs.parser.playerConnected(c);
|
||||
|
||||
Packet p(PacketType::THIS_PLAYER_INFO);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ServerClient.h"
|
||||
#include "../../lua/parser/ServerLuaParser.h"
|
||||
|
||||
|
@ -12,7 +13,7 @@ class ClientList {
|
|||
public:
|
||||
explicit ClientList(ServerGame& defs);
|
||||
|
||||
void handleConnect(ENetEvent e);
|
||||
void handleConnect(ENetEvent e, InventoryRefs& refs);
|
||||
void handleDisconnect(ENetEvent e);
|
||||
|
||||
void createPlayer(std::shared_ptr<ServerClient> c);
|
||||
|
|
|
@ -3,17 +3,20 @@
|
|||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "ServerClient.h"
|
||||
|
||||
#include "../../util/net/Packet.h"
|
||||
#include "../../util/net/Serializer.h"
|
||||
#include "../../game/inventory/InventoryRefs.h"
|
||||
#include "../../game/scene/net/NetPlayerField.h"
|
||||
|
||||
ServerClient::ServerClient(ENetPeer *peer, ENetAddress address, DefinitionAtlas& defs) :
|
||||
ServerClient::ServerClient(ENetPeer *peer, ENetAddress address, DefinitionAtlas& defs, InventoryRefs& refs) :
|
||||
peer(peer),
|
||||
address(address),
|
||||
cid(peer->connectID),
|
||||
hand(defs, "hand", 1, 1),
|
||||
inventory(defs) {}
|
||||
inventory(refs.createInv("player:" + std::to_string(cid))) {
|
||||
}
|
||||
|
||||
void ServerClient::setUsername(const std::string &name) {
|
||||
this->username = name;
|
||||
|
@ -92,6 +95,6 @@ unsigned long long ServerClient::getMapBlockIntegrity(glm::ivec3 pos) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Inventory &ServerClient::getInventory() {
|
||||
std::shared_ptr<Inventory> ServerClient::getInventory() {
|
||||
return inventory;
|
||||
}
|
|
@ -12,11 +12,13 @@
|
|||
#include "../../game/inventory/InventoryList.h"
|
||||
#include "../../game/inventory/Inventory.h"
|
||||
|
||||
class InventoryRefs;
|
||||
|
||||
class ServerClient {
|
||||
public:
|
||||
const static int CHUNK_SEND_RANGE = 32;
|
||||
|
||||
ServerClient(ENetPeer* peer, ENetAddress address, DefinitionAtlas& defs);
|
||||
ServerClient(ENetPeer* peer, ENetAddress address, DefinitionAtlas& defs, InventoryRefs& refs);
|
||||
|
||||
void setUsername(const std::string& name);
|
||||
|
||||
|
@ -38,11 +40,11 @@ public:
|
|||
void setMapBlockIntegrity(glm::ivec3 pos, unsigned long long integrity);
|
||||
unsigned long long getMapBlockIntegrity(glm::ivec3 pos);
|
||||
|
||||
Inventory& getInventory();
|
||||
std::shared_ptr<Inventory> getInventory();
|
||||
|
||||
bool hasPlayer = false;
|
||||
|
||||
unsigned int cid;
|
||||
unsigned int cid = 0;
|
||||
std::string username;
|
||||
|
||||
ENetPeer* peer;
|
||||
|
@ -58,8 +60,7 @@ private:
|
|||
|
||||
bool flying = false;
|
||||
|
||||
InventoryList hand;
|
||||
Inventory inventory;
|
||||
std::shared_ptr<Inventory> inventory;
|
||||
|
||||
std::unordered_map<glm::ivec3, unsigned long long, Vec::ivec3> mapBlockIntegrity {};
|
||||
};
|
||||
|
|
|
@ -23,7 +23,11 @@ enum class PacketType {
|
|||
CHUNK,
|
||||
BLOCK_SET,
|
||||
ENTITY_INFO,
|
||||
|
||||
// Inventory
|
||||
WATCH_INV,
|
||||
UNWATCH_INV
|
||||
UNWATCH_INV,
|
||||
INV_INVALID,
|
||||
INVENTORY
|
||||
};
|
||||
|
||||
|
|
|
@ -17,7 +17,11 @@ zepha.register_block("zeus:default:grass", {
|
|||
shovel = 1,
|
||||
pick = 2
|
||||
},
|
||||
drop = "zeus:default:dirt"
|
||||
drop = "zeus:default:dirt",
|
||||
on_break = fn(pos) {
|
||||
zepha.add_entity("zeus:default:dropped_item", vector.add(pos, v(0.5)),
|
||||
{item = zepha.registered_blocks["zeus:default:grass"].drop});
|
||||
}
|
||||
})
|
||||
|
||||
zepha.register_block("zeus:default:grass_slab", {
|
||||
|
|
|
@ -79,18 +79,21 @@ zepha.register_entity("zeus:default:dropped_item", {
|
|||
|
||||
if (self.tick > 0.15) {
|
||||
self.tick = 0
|
||||
if (zepha.client) { self:check_collect() }
|
||||
self:check_collect()
|
||||
}
|
||||
},
|
||||
check_collect = fn(self) {
|
||||
if (vector.distance(zepha.player.pos, self.object.pos) < 2) {
|
||||
self.object.pos = vector.add(zepha.player.pos, v(0, 0.90, 0))
|
||||
self.scooping = true
|
||||
foreach p in zepha.players {
|
||||
if (vector.distance(p.pos, self.object.pos) < 2) {
|
||||
self.object.pos = vector.add(p.pos, v(0, 0.90, 0))
|
||||
self.scooping = true
|
||||
|
||||
zepha.delay(() => {
|
||||
zepha.remove_entity(self)
|
||||
zepha.player:get_inventory():get_list("main"):add_stack({self.item, 1})
|
||||
}, 2/20)
|
||||
|
||||
zepha.delay(() => {
|
||||
zepha.remove_entity(self)
|
||||
p:get_inventory():get_list("main"):add_stack({self.item, 1})
|
||||
}, 2/20)
|
||||
}
|
||||
}
|
||||
},
|
||||
on_serialize = fn(self) {
|
||||
|
|
|
@ -33,11 +33,11 @@ zepha.register_keybind("zeus:default:open_chat", {
|
|||
on_press = () => { print "Opened chat!" }
|
||||
})
|
||||
|
||||
if (zepha.server) {
|
||||
zepha.delay(() => {
|
||||
foreach player in zepha.players {
|
||||
player:get_inventory():get_list("main"):add_stack({"zeus:default:dirt", 1})
|
||||
}
|
||||
return true
|
||||
}, 1/20)
|
||||
}
|
||||
##if (zepha.server) {
|
||||
## zepha.delay(() => {
|
||||
## foreach player in zepha.players {
|
||||
## player:get_inventory():get_list("main"):add_stack({"zeus:default:dirt", 1})
|
||||
## }
|
||||
## return true
|
||||
## }, 1/20)
|
||||
##}
|
|
@ -3,40 +3,6 @@ zepha.register_on("player_join", (p) => {
|
|||
local inv = p:get_inventory()
|
||||
local main = inv:add_list("main", 44, 11)
|
||||
|
||||
local shit_adding = false
|
||||
|
||||
zepha.register_keybind("zeus:inventory:add_shit_b", {
|
||||
description = "Add testing items to inventory",
|
||||
default = zepha.keys.b,
|
||||
on_press = () => { shit_adding = 1 },
|
||||
on_release = () => { shit_adding = 0 }
|
||||
})
|
||||
|
||||
zepha.register_keybind("zeus:inventory:add_shit_i", {
|
||||
description = "Add testing items to inventory",
|
||||
default = zepha.keys.n,
|
||||
on_press = () => { shit_adding = 2 },
|
||||
on_release = () => { shit_adding = 0 }
|
||||
})
|
||||
|
||||
zepha.delay(() => {
|
||||
if (shit_adding == 1) {
|
||||
main:add_stack({"zeus:default:cobblestone", 1})
|
||||
main:add_stack({"zeus:default:tallgrass_5", 1})
|
||||
main:add_stack({"zeus:default:leaves", 1})
|
||||
main:add_stack({"zeus:kinetic:axle_0", 1})
|
||||
main:add_stack({"zeus:default:wood", 1})
|
||||
}
|
||||
|
||||
if (shit_adding == 2) {
|
||||
main:add_stack({"zeus:materials:plant_fibre", 1})
|
||||
main:add_stack({"zeus:materials:plant_twine", 1})
|
||||
main:add_stack({"zeus:materials:stick", 1})
|
||||
main:add_stack({"zeus:materials:flint", 1})
|
||||
}
|
||||
return true
|
||||
}, 0)
|
||||
|
||||
## Bind crafting
|
||||
|
||||
local craft_input = inv:add_list("craft", 4, 2)
|
||||
|
@ -44,7 +10,7 @@ zepha.register_on("player_join", (p) => {
|
|||
|
||||
crafting.bind(craft_input, craft_output)
|
||||
|
||||
## Make hotwheel
|
||||
## Make hot wheel
|
||||
|
||||
local invs = {
|
||||
inv:add_list("hot_wheel_1", 5, 5),
|
||||
|
|
Loading…
Reference in New Issue