165 lines
5.2 KiB
C++
165 lines
5.2 KiB
C++
#include "ClientMessageHandler.hpp"
|
|
|
|
#include "../Chatbox.hpp"
|
|
#include "../Game.hpp"
|
|
#include "../GameState.hpp"
|
|
#include "msgtypes/BlockUpdate.hpp"
|
|
#include "msgtypes/Chat.hpp"
|
|
#include "msgtypes/ChunkTransfer.hpp"
|
|
|
|
namespace Diggler {
|
|
namespace Net {
|
|
|
|
ClientMessageHandler::ClientMessageHandler(GameState &gameState) :
|
|
GS(gameState) {
|
|
}
|
|
|
|
bool ClientMessageHandler::handleMessage(InMessage &msg) {
|
|
using namespace Net::MsgTypes;
|
|
switch (msg.getType()) {
|
|
case MessageType::NetDisconnect:
|
|
GS.GW->showMessage("Disconnected", "Timed out");
|
|
return false;
|
|
|
|
case MessageType::ChunkTransfer: {
|
|
using S = ChunkTransferSubtype;
|
|
switch (static_cast<S>(msg.getSubtype())) {
|
|
case S::Request: {
|
|
; // No-op
|
|
} break;
|
|
case S::Response: {
|
|
ChunkTransferResponse ctr;
|
|
ctr.readFromMsg(msg);
|
|
for (const ChunkTransferResponse::ChunkData &cd : ctr.chunks) {
|
|
ChunkRef c = GS.G->U->getLoadWorld(cd.worldId)->getNewEmptyChunk(
|
|
cd.chunkPos.x, cd.chunkPos.y, cd.chunkPos.z);
|
|
InMemoryStream ims(cd.data, cd.dataLength);
|
|
c->read(ims);
|
|
GS.holdChunksInMem.push_back(c);
|
|
}
|
|
} break;
|
|
case S::Denied: {
|
|
ChunkTransferDenied ctd;
|
|
ctd.readFromMsg(msg);
|
|
} break;
|
|
}
|
|
} break;
|
|
case MessageType::Chat: {
|
|
using S = ChatSubtype;
|
|
switch (static_cast<S>(msg.getSubtype())) {
|
|
case S::Send: {
|
|
; // No-op
|
|
} break;
|
|
case S::Announcement: {
|
|
ChatAnnouncement ca;
|
|
ca.readFromMsg(msg);
|
|
// TODO better formatting abilities
|
|
if (ca.msg.type == msgpack::type::STR) {
|
|
GS.m_chatBox->addChatEntry(ca.msg.as<std::string>());
|
|
}
|
|
} break;
|
|
case S::PlayerTalk: {
|
|
ChatPlayerTalk cpt;
|
|
cpt.readFromMsg(msg);
|
|
// TODO better formatting abilities
|
|
if (cpt.msg.type == msgpack::type::STR) {
|
|
std::string playerName;
|
|
if (cpt.player.display.type == msgpack::type::NIL) {
|
|
const Player *blabbermouth = GS.G->players.getByGameId(cpt.player.id);
|
|
if (blabbermouth != nullptr) {
|
|
playerName = blabbermouth->name + "> ";
|
|
} else {
|
|
playerName = "?> ";
|
|
}
|
|
} else if (cpt.player.display.type == msgpack::type::STR) {
|
|
cpt.player.display.convert(playerName);
|
|
}
|
|
GS.m_chatBox->addChatEntry(playerName + cpt.msg.as<std::string>());
|
|
}
|
|
} break;
|
|
}
|
|
} break;
|
|
case MessageType::PlayerJoin: {
|
|
Player &plr = GS.G->players.add();
|
|
plr.id = msg.readU32();
|
|
plr.name = msg.readString();
|
|
getDebugStream() << "Player " << plr.name << '(' << plr.id << ") joined the party!" << std::endl;
|
|
} break;
|
|
case MessageType::PlayerQuit: {
|
|
uint32 id = msg.readU32();
|
|
try {
|
|
Player *plr = GS.G->players.getByGameId(id);
|
|
if (plr != nullptr) {
|
|
getOutputStream() << plr->name << " is gone :(" << std::endl;
|
|
GS.G->players.remove(*plr);
|
|
}
|
|
} catch (const std::out_of_range &e) {
|
|
getOutputStream() << "Phantom player #" << id << " disconnected" << std::endl;
|
|
}
|
|
} break;
|
|
case MessageType::PlayerUpdate: {
|
|
uint32 id = msg.readU32();
|
|
try {
|
|
Player *plr = GS.G->players.getByGameId(id);
|
|
if (plr != nullptr) {
|
|
switch (msg.getSubtype()) {
|
|
case PlayerUpdateType::Move: {
|
|
glm::vec3 pos = msg.readVec3(),
|
|
vel = msg.readVec3(),
|
|
acc = msg.readVec3();
|
|
plr->setPosVel(pos, vel, acc);
|
|
plr->angle = msg.readFloat();
|
|
} break;
|
|
case PlayerUpdateType::Die:
|
|
plr->setDead(false, (Player::DeathReason)msg.readU8());
|
|
break;
|
|
case PlayerUpdateType::Respawn:
|
|
plr->setDead(false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} catch (const std::out_of_range &e) {
|
|
getOutputStream() << "Invalid player update: #" << id << " is not on server" << std::endl;
|
|
}
|
|
} break;
|
|
case MessageType::BlockUpdate: {
|
|
// TODO handle that in Chunk's ChangeHelper
|
|
using S = BlockUpdateSubtype;
|
|
switch (static_cast<S>(msg.getSubtype())) {
|
|
case S::Notify: {
|
|
BlockUpdateNotify bun;
|
|
bun.readFromMsg(msg);
|
|
for (const BlockUpdateNotify::UpdateData &upd : bun.updates) {
|
|
WorldRef w = GS.G->U->getWorld(upd.worldId);
|
|
if (w) {
|
|
ChunkRef c = w->getChunkAtCoords(upd.pos);
|
|
if (c) {
|
|
c->setBlock(rmod(upd.pos.x, CX), rmod(upd.pos.y, CY), rmod(upd.pos.z, CZ),
|
|
upd.id, upd.data);
|
|
// TODO extdata & light
|
|
}
|
|
}
|
|
}
|
|
} break;
|
|
case S::Place:
|
|
case S::Break: {
|
|
; // No-op
|
|
} break;
|
|
}
|
|
} break;
|
|
|
|
case MessageType::ServerInfo:
|
|
case MessageType::NetConnect:
|
|
case MessageType::Null:
|
|
default: {
|
|
; // No-op
|
|
} break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|