#include "DedicatedServer.h" #include "config/ServerProperties.h" #include "PacketReader.h" namespace Feather { DedicatedServer::DedicatedServer(ServerProperties* properties) : m_properties(properties), m_listener(properties->serverPort.GetValue(), this), m_status() { m_status.descriptionText = properties->motd.GetValue(); m_status.maxPlayers = properties->maxPlayers.GetValue(); while (1) { auto [clients, clientsLock] = m_clients.borrow(); for (auto& client : clients) { auto [data, clientLock] = client.GetTCPClient()->GetData().borrow(); if (data.empty()) continue; uint32_t offset = 0; while (offset != data.size()) { auto reader = PacketReader(&data[offset]); Protocol::ProcessPacket(*this, client, reader, client.GetContext().GetState()); offset += reader.Size(); } data.clear(); } } } DedicatedServer::~DedicatedServer() { } void DedicatedServer::OnClientConnect(Network::TCPClientHandle&& client) { const auto& address = client->GetAddress(); Log_Info("New connection from %s:%hu", address.ip, address.port); auto [clients, lock] = m_clients.borrow(); clients.emplace_back(std::move(client)); } void DedicatedServer::OnClientDisconnect(const Network::TCPClient* client) { const auto& address = client->GetAddress(); Log_Info("Disconnected from %s:%hu", address.ip, address.port); auto [clients, lock] = m_clients.borrow(); clients.remove_if([&](MinecraftClient& other) { return other.GetTCPClient().get() == client; }); } using namespace Protocol; void DedicatedServer::HandleLegacyPing(MinecraftClient& client) { Log_Info("Got legacy server list ping."); } template <> void DedicatedServer::HandlePacket(MinecraftClient& client, const Handholding::ServerboundHandshake& handshake) { Log_Info("Client Intention Packet: version=%d, serverIp=%s, port=%u, intention=%d\n", handshake.protocolVersion, handshake.serverIP.c_str(), handshake.port, handshake.intention ); client.GetContext().SetState(handshake.intention); } template <> void DedicatedServer::HandlePacket(MinecraftClient& client, const Status::ServerboundRequest& request) { Log_Info("Client sent STATUS_PING_REQUEST"); Status::ClientboundResponse message = { .jsonResponse = m_status.GetServerStatusJSON() }; client.SendMessage(message); } template <> void DedicatedServer::HandlePacket(MinecraftClient& client, const Status::ServerboundPing& ping) { Log_Info("Client sent STATUS_PING: %llu", ping.timestamp); Status::ClientboundPong message = { .timestamp = ping.timestamp }; client.SendMessage(message); } template <> void DedicatedServer::HandlePacket(MinecraftClient& client,const Login::ServerboundStart& start) { //Login::ClientboundSuccess success = //{ // .uuid = { 4658857991808325907ull, 7518717155607718277ull }, // .username = start.username //}; std::string uuid = "ecb99913-96a8-40a7-8529-a2ca6ad95768"; Login::ClientboundSuccess success = { .uuid = uuid, .username = start.username }; client.SendMessage(success); client.GetContext().SetState(ProtocolState::Play); std::string type = "default"; Play::ClientboundJoinGame join = { .entityId = 0, .gamemode = 0, .dimension = 0, .seedHash = 0, .maxPlayers = uint8_t(m_properties->maxPlayers.GetValue()), .levelType = type, .viewDistance = m_properties->viewDistance, .reducedDebugInfo = false, .enableRespawnScreen = true }; client.SendMessage(join); Play::ClientboundSpawnPosition spawnPos = { .location = BlockPos(0, 64, 0), }; client.SendMessage(spawnPos); using RelativeFlags = Play::ClientboundPlayerPositionAndLook::RelativeFlags; Play::ClientboundPlayerPositionAndLook playerPos = { .x = 0, .y = 64, .z = 0, .xRot = 0, .yRot = 0, .flags = (RelativeFlags)0, .id = 0, }; client.SendMessage(playerPos); } }