[WorldSaveBasicBackend] Now saving player position, rotation and inventory.

This commit is contained in:
Quentin Bazin 2020-06-26 04:52:04 +02:00
parent 3c957d9889
commit 057753f1d2
17 changed files with 132 additions and 59 deletions

View File

@ -91,6 +91,8 @@ _This packet has no field._
| Player Z | double | Player Z coordinate |
| Dimension | u16 | Dimension ID |
| Username | std::string | Name of the player |
| Camera Yaw | float | Horizontal camera view angle |
| Camera Pitch | float | Vertical camera view angle |
#### PlayerChangeDimension

View File

@ -231,12 +231,15 @@ void ClientCommandHandler::setupCallbacks() {
gk::Vector3d pos;
u16 dimension;
std::string username;
packet >> clientId >> pos.x >> pos.y >> pos.z >> dimension >> username;
float cameraYaw, cameraPitch;
packet >> clientId >> pos.x >> pos.y >> pos.z >> dimension
>> username >> cameraYaw >> cameraPitch;
if (clientId != m_client.id()) {
m_playerBoxes.emplace(clientId, PlayerBox{m_player.camera()});
Player &player = m_playerBoxes.at(clientId);
player.setPosition(pos.x, pos.y, pos.z);
player.setRotation(cameraYaw, cameraPitch);
player.setDimension(dimension);
player.setClientID(clientId);
player.setName(username);
@ -244,6 +247,8 @@ void ClientCommandHandler::setupCallbacks() {
}
else {
m_player.setPosition(pos.x, pos.y, pos.z);
m_player.setRotation(cameraYaw, cameraPitch);
m_player.updateCamera();
}
});

View File

@ -43,7 +43,7 @@ ClientPlayer::ClientPlayer(gk::Camera &camera) : m_camera(camera) {
m_viewAngleV = 0.f;
m_viewAngleRoll = 0.f;
updateDir();
updateCamera();
m_camera.setDPosition(m_x + m_cameraLocalPos.x, m_y + m_cameraLocalPos.y, m_z + m_cameraLocalPos.z);
}
@ -53,16 +53,16 @@ void ClientPlayer::turnH(float angle) {
if (m_viewAngleH >= 180.f) m_viewAngleH -= 360.f;
if (m_viewAngleH < -180.f) m_viewAngleH += 360.f;
updateDir();
updateCamera();
}
void ClientPlayer::turnViewV(float angle) {
m_viewAngleV = std::max(std::min(m_viewAngleV + angle, 90.f), -90.f);
updateDir();
updateCamera();
}
void ClientPlayer::updateDir() {
void ClientPlayer::updateCamera() {
float ch = cosf(m_viewAngleH * RADIANS_PER_DEGREES);
float sh = sinf(m_viewAngleH * RADIANS_PER_DEGREES);
float cv = cosf(m_viewAngleV * RADIANS_PER_DEGREES);

View File

@ -52,6 +52,8 @@ class ClientPlayer : public Player {
void turnH(float angle);
void turnViewV(float angle);
void updateCamera();
void move(float direction);
void processInputs();
@ -67,13 +69,12 @@ class ClientPlayer : public Player {
static void setInstance(ClientPlayer *instance) { s_instance = instance; }
void setPosition(double x, double y, double z);
void setCameraRoll(float angle) { m_viewAngleRoll = angle; updateDir(); };
void setCameraRoll(float angle) { m_viewAngleRoll = angle; updateCamera(); };
gk::Camera &camera() { return m_camera; }
private:
void testPoint(const ClientWorld &world, double x, double y, double z, glm::vec3 &vel);
void updateDir();
static ClientPlayer *s_instance;

View File

@ -42,11 +42,11 @@ u8 Player::getOppositeDirection() const {
}
void Player::serialize(sf::Packet &packet) const {
packet << m_x << m_y << m_z << m_dimension << m_inventory << m_name;
packet << m_x << m_y << m_z << m_dimension << m_viewAngleH << m_viewAngleV << m_viewAngleRoll << m_inventory;
}
void Player::deserialize(sf::Packet &packet) {
packet >> m_x >> m_y >> m_z >> m_dimension >> m_inventory >> m_name;
packet >> m_x >> m_y >> m_z >> m_dimension >> m_viewAngleH >> m_viewAngleV >> m_viewAngleRoll >> m_inventory;
}
// Please update 'docs/lua-api-cpp.md' if you change this

View File

@ -26,30 +26,61 @@
*/
#include "PlayerList.hpp"
ServerPlayer &PlayerList::addPlayer(ClientInfo &client) {
m_players.emplace(client.id, client);
return m_players.at(client.id);
ServerPlayer &PlayerList::addPlayer(const std::string &name, bool isNewPlayer) {
m_players.emplace(name, ServerPlayer{name, isNewPlayer});
return m_players.at(name);
}
void PlayerList::removePlayer(u16 id) {
auto it = m_players.find(id);
if (it != m_players.end())
m_players.erase(it);
ServerPlayer &PlayerList::connectPlayer(const std::string &name, ClientInfo &client) {
ServerPlayer *player = nullptr;
auto it = m_players.find(name);
if (it != m_players.end()) {
player = &it->second;
gkInfo() << name << "is online";
}
else {
player = &addPlayer(name, true);
gkInfo() << name << "is online (first connection)";
}
player->setClient(&client);
player->setClientID(client.id);
client.playerName = name;
return *player;
}
const ServerPlayer *PlayerList::getPlayer(u16 id) const {
auto it = m_players.find(id);
void PlayerList::disconnectPlayer(const std::string &name) {
auto it = m_players.find(name);
if (it != m_players.end()) {
it->second.setClient(nullptr);
it->second.setNewPlayer(false);
}
}
const ServerPlayer *PlayerList::getPlayer(const std::string &name) const {
auto it = m_players.find(name);
if (it == m_players.end())
return nullptr;
return &it->second;
}
ServerPlayer *PlayerList::getPlayer(u16 id) {
auto it = m_players.find(id);
ServerPlayer *PlayerList::getPlayer(const std::string &name) {
auto it = m_players.find(name);
if (it == m_players.end())
return nullptr;
return &it->second;
}
ServerPlayer *PlayerList::getPlayerFromClientID(u16 clientID) {
for (auto &it : m_players) {
if (it.second.clientID() == clientID)
return &it.second;
}
return nullptr;
}

View File

@ -32,16 +32,19 @@
#include "ServerPlayer.hpp"
class PlayerList {
using PlayerMap = std::unordered_map<u16, ServerPlayer>;
using PlayerMap = std::unordered_map<std::string, ServerPlayer>;
using Iterator = PlayerMap::iterator;
using ConstIterator = PlayerMap::const_iterator;
public:
ServerPlayer &addPlayer(ClientInfo &client);
void removePlayer(u16 id);
ServerPlayer &addPlayer(const std::string &name, bool isNewPlayer);
ServerPlayer &connectPlayer(const std::string &name, ClientInfo &client);
void disconnectPlayer(const std::string &name);
const ServerPlayer *getPlayer(u16 id) const;
ServerPlayer *getPlayer(u16 id);
const ServerPlayer *getPlayer(const std::string &name) const;
ServerPlayer *getPlayer(const std::string &name);
ServerPlayer *getPlayerFromClientID(u16 clientID);
Iterator begin() { return m_players.begin(); }
Iterator end() { return m_players.end(); }
@ -49,6 +52,8 @@ class PlayerList {
ConstIterator begin() const { return m_players.begin(); }
ConstIterator end() const { return m_players.end(); }
std::size_t size() const { return m_players.size(); }
private:
PlayerMap m_players;
};

View File

@ -179,8 +179,10 @@ void ServerApplication::update() {
if (m_clock.getTicks() % 100 < 10) {
for (auto &it : m_players) {
m_serverCommandHandler.sendPlayerPosUpdate(it.first);
m_serverCommandHandler.sendPlayerRotUpdate(it.first);
if (it.second.isOnline()) {
m_serverCommandHandler.sendPlayerPosUpdate(it.second.clientID());
m_serverCommandHandler.sendPlayerRotUpdate(it.second.clientID());
}
}
}
}

View File

@ -109,7 +109,7 @@ void LuaMod::despawnEntity(EntityWrapper &entity) {
void LuaMod::giveItemStack(ServerPlayer &player, ItemStack *itemStack) {
if (itemStack) {
player.inventory().addStack(itemStack->item().stringID(), itemStack->amount());
m_worldController.server()->sendPlayerInvUpdate(player.clientID(), &player.client());
m_worldController.server()->sendPlayerInvUpdate(player.clientID(), player.client());
}
else
gkError() << "In mod '" + m_id + "': Failed to add stack to player";

View File

@ -46,6 +46,8 @@ class ClientInfo {
std::shared_ptr<sf::TcpSocket> tcpSocket;
NetworkInputHandler inputHandler;
std::string playerName;
};
#endif // CLIENTINFO_HPP_

View File

@ -68,7 +68,7 @@ void ServerCommandHandler::sendBlockInvUpdate(s32 x, s32 y, s32 z, const Invento
}
void ServerCommandHandler::sendPlayerPosUpdate(u16 clientID, bool isTeleportation, const ClientInfo *client) const {
const ServerPlayer *player = m_players.getPlayer(clientID);
const ServerPlayer *player = m_players.getPlayerFromClientID(clientID);
if (player) {
Network::Packet packet;
packet << Network::Command::PlayerPosUpdate;
@ -86,7 +86,7 @@ void ServerCommandHandler::sendPlayerPosUpdate(u16 clientID, bool isTeleportatio
}
void ServerCommandHandler::sendPlayerRotUpdate(u16 clientID, const ClientInfo *client) const {
const ServerPlayer *player = m_players.getPlayer(clientID);
const ServerPlayer *player = m_players.getPlayerFromClientID(clientID);
if (player) {
Network::Packet packet;
packet << Network::Command::PlayerRotUpdate;
@ -103,7 +103,7 @@ void ServerCommandHandler::sendPlayerRotUpdate(u16 clientID, const ClientInfo *c
}
void ServerCommandHandler::sendPlayerInvUpdate(u16 clientID, const ClientInfo *client) const {
ServerPlayer *player = m_players.getPlayer(clientID);
ServerPlayer *player = m_players.getPlayerFromClientID(clientID);
if (player) {
Network::Packet packet;
packet << Network::Command::PlayerInvUpdate;
@ -170,9 +170,9 @@ void ServerCommandHandler::setupCallbacks() {
std::string username;
connectionPacket >> username;
auto &player = m_players.addPlayer(client);
player.setPosition(m_spawnPosition.x, m_spawnPosition.y, m_spawnPosition.z);
player.setName(username);
auto &player = m_players.connectPlayer(username, client);
if (player.isNewPlayer())
player.setPosition(m_spawnPosition.x, m_spawnPosition.y, m_spawnPosition.z);
Network::Packet packet;
packet << Network::Command::RegistryData;
@ -183,11 +183,13 @@ void ServerCommandHandler::setupCallbacks() {
for (auto &it : m_players) {
Network::Packet spawnPacket;
spawnPacket << Network::Command::PlayerSpawn << it.first;
spawnPacket << it.second.x() << it.second.y() << it.second.z();
spawnPacket << it.second.x() << it.second.y() << it.second.z() << it.second.dimension() << it.second.name();
spawnPacket << it.second.cameraYaw() << it.second.cameraPitch();
client.tcpSocket->send(spawnPacket);
}
m_scriptEngine.luaCore().onEvent(LuaEventType::PlayerConnected, glm::ivec3{m_spawnPosition.x, m_spawnPosition.y, m_spawnPosition.z}, player, client, *this);
if (player.isNewPlayer())
m_scriptEngine.luaCore().onEvent(LuaEventType::PlayerConnected, glm::ivec3{player.x(), player.y(), player.z()}, player, client, *this);
Network::Packet invPacket;
invPacket << Network::Command::PlayerInvUpdate << client.id;
@ -198,6 +200,7 @@ void ServerCommandHandler::setupCallbacks() {
Network::Packet spawnPacket;
spawnPacket << Network::Command::PlayerSpawn << client.id;
spawnPacket << player.x() << player.y() << player.z() << player.dimension() << player.name();
spawnPacket << player.cameraYaw() << player.cameraPitch();
m_server.sendToAllClients(spawnPacket);
// Send entities to the client
@ -205,7 +208,7 @@ void ServerCommandHandler::setupCallbacks() {
});
m_server.setCommandCallback(Network::Command::ClientDisconnect, [this](ClientInfo &client, Network::Packet &) {
m_players.removePlayer(client.id);
m_players.disconnectPlayer(client.playerName);
});
m_server.setCommandCallback(Network::Command::ChunkRequest, [this](ClientInfo &client, Network::Packet &packet) {
@ -216,7 +219,7 @@ void ServerCommandHandler::setupCallbacks() {
});
m_server.setCommandCallback(Network::Command::PlayerInvUpdate, [this](ClientInfo &client, Network::Packet &packet) {
ServerPlayer *player = m_players.getPlayer(client.id);
ServerPlayer *player = m_players.getPlayerFromClientID(client.id);
if (player) {
packet >> player->inventory();
}
@ -228,7 +231,7 @@ void ServerCommandHandler::setupCallbacks() {
double x, y, z;
packet >> x >> y >> z;
ServerPlayer *player = m_players.getPlayer(client.id);
ServerPlayer *player = m_players.getPlayerFromClientID(client.id);
if (player) {
player->setPosition(x, y, z);
}
@ -240,7 +243,7 @@ void ServerCommandHandler::setupCallbacks() {
float yaw, pitch;
packet >> yaw >> pitch;
ServerPlayer *player = m_players.getPlayer(client.id);
ServerPlayer *player = m_players.getPlayerFromClientID(client.id);
if (player) {
player->setRotation(yaw, pitch);
}
@ -249,7 +252,7 @@ void ServerCommandHandler::setupCallbacks() {
});
m_server.setCommandCallback(Network::Command::PlayerPlaceBlock, [this](ClientInfo &client, Network::Packet &packet) {
ServerPlayer *player = m_players.getPlayer(client.id);
ServerPlayer *player = m_players.getPlayerFromClientID(client.id);
if (player) {
s32 x, y, z;
u32 block;
@ -271,7 +274,7 @@ void ServerCommandHandler::setupCallbacks() {
});
m_server.setCommandCallback(Network::Command::PlayerDigBlock, [this](ClientInfo &client, Network::Packet &packet) {
ServerPlayer *player = m_players.getPlayer(client.id);
ServerPlayer *player = m_players.getPlayerFromClientID(client.id);
if (player) {
s32 x, y, z;
packet >> x >> y >> z;
@ -291,7 +294,7 @@ void ServerCommandHandler::setupCallbacks() {
});
m_server.setCommandCallback(Network::Command::PlayerHeldItemChanged, [this](ClientInfo &client, Network::Packet &packet) {
ServerPlayer *player = m_players.getPlayer(client.id);
ServerPlayer *player = m_players.getPlayerFromClientID(client.id);
if (player) {
u8 hotbarSlot;
u16 itemID;
@ -306,7 +309,7 @@ void ServerCommandHandler::setupCallbacks() {
});
m_server.setCommandCallback(Network::Command::BlockActivated, [this](ClientInfo &client, Network::Packet &packet) {
ServerPlayer *player = m_players.getPlayer(client.id);
ServerPlayer *player = m_players.getPlayerFromClientID(client.id);
if (player) {
s32 x, y, z;
u16 screenWidth, screenHeight;
@ -372,7 +375,7 @@ void ServerCommandHandler::setupCallbacks() {
}
void ServerCommandHandler::setPlayerPosition(u16 clientID, s32 x, s32 y, s32 z) {
ServerPlayer *player = m_players.getPlayer(clientID);
ServerPlayer *player = m_players.getPlayerFromClientID(clientID);
if (player)
player->setPosition(x, y, z);
else
@ -380,7 +383,7 @@ void ServerCommandHandler::setPlayerPosition(u16 clientID, s32 x, s32 y, s32 z)
}
inline ServerWorld &ServerCommandHandler::getWorldForClient(u16 clientID) {
ServerPlayer *player = m_players.getPlayer(clientID);
ServerPlayer *player = m_players.getPlayerFromClientID(clientID);
if (!player)
throw EXCEPTION("Player instance not found for client", clientID);

View File

@ -26,10 +26,6 @@
*/
#include "ServerPlayer.hpp"
ServerPlayer::ServerPlayer(ClientInfo &client) : m_client(client) {
m_clientID = client.id;
}
// Please update 'docs/lua-api-cpp.md' if you change this
void ServerPlayer::initUsertype(sol::state &lua) {
lua.new_usertype<ServerPlayer>("ServerPlayer",

View File

@ -34,24 +34,30 @@
class ServerPlayer : public Player {
public:
ServerPlayer(ClientInfo &client);
ServerPlayer(const std::string &name, bool isNewPlayer) {
m_name = name;
m_isNewPlayer = isNewPlayer;
}
const ClientInfo &client() const { return m_client; }
const ClientInfo *client() const { return m_client; }
void setClient(ClientInfo *client) { m_client = client; }
const ItemStack &heldItemStack() { return m_inventory.getStack(m_heldItemSlot, 0); }
void setHeldItemSlot(u8 heldItemSlot) { m_heldItemSlot = heldItemSlot; }
bool isOnline() const { return m_isOnline; }
void setOnline(bool isOnline) { m_isOnline = isOnline; }
bool isOnline() const { return m_client != nullptr; }
bool isNewPlayer() const { return m_isNewPlayer; }
void setNewPlayer(bool isNewPlayer) { m_isNewPlayer = isNewPlayer; }
static void initUsertype(sol::state &lua);
private:
ClientInfo &m_client;
ClientInfo *m_client = nullptr;
u8 m_heldItemSlot = 0;
bool m_isOnline = false;
bool m_isNewPlayer = false;
};
#endif // SERVERPLAYER_HPP_

View File

@ -48,7 +48,7 @@ void ServerWorld::update() {
if (it.second->isInitialized() && !it.second->isSent()) {
for (auto &client : m_server->server().info().clients())
if (m_players.getPlayer(client.id)->dimension() == m_dimension.id())
if (m_players.getPlayer(client.playerName)->dimension() == m_dimension.id())
sendChunkData(client, *it.second.get());
// gkDebug() << "Chunk updated at" << it.second->x() << it.second->y() << it.second->z();

View File

@ -34,7 +34,7 @@ void WorldController::init(PlayerList &players) {
m_worldList.back().setServer(m_server);
}
m_worldSaveBackend.reset(new WorldSaveBasicBackend{m_worldList});
m_worldSaveBackend.reset(new WorldSaveBasicBackend{m_worldList, players});
}
void WorldController::clearEntities() {

View File

@ -101,6 +101,16 @@ void WorldSaveBasicBackend::load(const std::string &name) {
loadEntities(save, world);
}
u16 playerCount;
save >> playerCount;
for (u16 i = 0 ; i < playerCount ; ++i) {
std::string username;
save >> username;
auto &player = m_playerList.addPlayer(username, false);
player.deserialize(save);
}
}
// gkInfo() << "Loading done.";
@ -150,6 +160,13 @@ void WorldSaveBasicBackend::save(const std::string &name) {
saveEntities(save, world);
}
save << (u16)m_playerList.size();
for (auto &it : m_playerList) {
save << it.second.name();
save << it.second;
}
file.write((const char *)save.getData(), save.getDataSize());
// gkInfo() << "Saving done.";

View File

@ -32,6 +32,7 @@
#include <entt/entt.hpp>
#include "PlayerList.hpp"
#include "WorldSaveBackend.hpp"
namespace sf { class Packet; }
@ -40,8 +41,8 @@ class ServerWorld;
class WorldSaveBasicBackend : public WorldSaveBackend {
public:
WorldSaveBasicBackend(std::deque<ServerWorld> &worldList)
: m_worldList(worldList) {}
WorldSaveBasicBackend(std::deque<ServerWorld> &worldList, PlayerList &playerList)
: m_worldList(worldList), m_playerList(playerList) {}
void load(const std::string &worldName) override;
void save(const std::string &worldName) override;
@ -52,6 +53,8 @@ class WorldSaveBasicBackend : public WorldSaveBackend {
std::deque<ServerWorld> &m_worldList;
PlayerList &m_playerList;
std::unordered_map<entt::entity, entt::entity> m_entityMap;
};