fekalnigtacko/src/server/client.cpp
2026-03-14 20:31:48 +01:00

100 lines
2.1 KiB
C++

#include "client.hpp"
#include <format>
#include "server.hpp"
#include "utils/validate.hpp"
#include "utils/version.hpp"
sv::Client::Client(Server& server, WSConnId id) : server_(server), id_(id) {}
bool sv::Client::ProcessMessage(net::InMessage& msg)
{
while (true)
{
net::MessageType type = net::MSG_NONE;
if (!msg.Read(type))
return true;
if (type == net::MSG_NONE || type >= net::MSG_COUNT)
return false;
ProcessSingleMessage(type, msg);
}
}
bool sv::Client::ProcessSingleMessage(net::MessageType type, net::InMessage& msg)
{
if (state_ == CS_PLAYER)
return player_->ProcessMsg(type, msg);
if (state_ == CS_INIT)
{
// allow only login
if (type != net::MSG_ID)
return false;
return ProcessLoginMsg(msg);
}
return false;
}
void sv::Client::Update()
{
if (player_)
{
player_->Update();
auto msg = player_->GetMsg();
if (!msg.empty())
{
Send(std::string(msg.data(), msg.size()));
player_->ResetMsg();
}
}
}
void sv::Client::SendChat(const std::string& text)
{
// not buffering till update here (unlike in Player), sent instantly
static std::vector<char> msg_buf;
msg_buf.clear();
net::OutMessage msg(msg_buf);
msg.Write(net::MSG_CHAT);
msg.Write(net::ChatMessage(text));
Send(std::string(msg_buf.data(), msg_buf.size()));
}
void sv::Client::Disconnect()
{
server_.Disconnect(*this);
}
void sv::Client::Send(std::string msg)
{
server_.Send(*this, std::move(msg));
}
bool sv::Client::ProcessLoginMsg(net::InMessage& msg)
{
net::Version ver = 0;
msg.Read(ver);
// check ver
if (ver != FEKAL_VERSION)
{
SendChat(std::format("^f55špatná verze {}, server je na verzi {}", ver, FEKAL_VERSION));
return false;
}
net::PlayerName name;
if (!msg.Read(name) || !utils::IsAlphanumeric(name))
return false;
player_ = std::make_unique<game::Player>(server_.GetGame(), name);
state_ = CS_PLAYER;
return true;
}