Splitted different client states into classes

This commit is contained in:
2020-07-16 23:18:19 +01:00
parent 63896c5090
commit b39078eedc
17 changed files with 699 additions and 324 deletions

View File

@@ -5,11 +5,21 @@ CONFIG += c++1z
DEFINES += QT_DEPRECATED_WARNINGS QT_DISABLE_DEPRECATED_BEFORE=0x060000
SOURCES += main.cpp \
client.cpp \
closedclient.cpp \
handshakingclient.cpp \
loginclient.cpp \
mcdatastream.cpp \
packets.cpp
packets.cpp \
playclient.cpp \
server.cpp \
statusclient.cpp
HEADERS += \
client.h \
closedclient.h \
handshakingclient.h \
loginclient.h \
mcdatastream.h \
packets.h
packets.h \
playclient.h \
server.h \
statusclient.h

View File

@@ -1,45 +0,0 @@
#pragma once
#include <QObject>
#include <QDateTime>
#include "mcdatastream.h"
#include "packets.h"
class QTcpSocket;
class Client : public QObject
{
Q_OBJECT
public:
explicit Client(QTcpSocket *socket, QObject *parent = nullptr);
SocketState state() const { return m_state; }
void keepAlive();
void sendChatMessage();
void trialDisconnect();
private Q_SLOTS:
void readyRead();
void disconnected();
private:
void readPacketHandshaking(const packets::handshaking::serverbound::PacketType type, const QByteArray &buffer);
void readPacketStatus(const packets::status::serverbound::PacketType type, const QByteArray &buffer);
void readPacketLogin(const packets::login::serverbound::PacketType type, const QByteArray &buffer);
void readPacketPlay(const packets::play::serverbound::PacketType type, const QByteArray &buffer);
QTcpSocket *m_socket;
McDataStream m_dataStream;
qint32 m_packetSize;
SocketState m_state;
const QDateTime m_connectedSince;
QDateTime m_lastKeepAliveSent;
QDateTime m_lastKeepAliveReceived;
QDateTime m_lastChatMessage;
};

49
closedclient.cpp Normal file
View File

@@ -0,0 +1,49 @@
#include "closedclient.h"
#include <QTcpSocket>
#include <QTimer>
#include "server.h"
ClosedClient::ClosedClient(QTcpSocket &socket, Server &server) :
QObject{&server}, m_socket{socket}, m_server{server}, m_dataStream{&m_socket}
{
m_socket.setParent(this);
connect(&m_socket, &QIODevice::readyRead, this, &ClosedClient::readyRead);
connect(&m_socket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
QTimer::singleShot(1000, this, &QObject::deleteLater);
}
void ClosedClient::readyRead()
{
while(m_socket.bytesAvailable())
{
if(!m_packetSize)
{
m_packetSize = m_dataStream.readVar<qint32>();
qDebug() << "packet size" << m_packetSize;
}
if(m_socket.bytesAvailable() < m_packetSize)
{
qWarning() << "packet not fully available" << m_socket.bytesAvailable();
return;
}
qint32 bytesRead;
const auto type = m_dataStream.readVar<qint32>(bytesRead);
m_packetSize -= bytesRead;
const auto buffer = m_socket.read(m_packetSize);
Q_ASSERT(buffer.size() == m_packetSize);
m_packetSize = 0;
readPacket(packets::closed::serverbound::PacketType(type), buffer);
}
}
void ClosedClient::readPacket(packets::closed::serverbound::PacketType type, const QByteArray &buffer)
{
qWarning() << "does not support receiving any packets" << type << buffer;
}

32
closedclient.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include <QObject>
#include "mcdatastream.h"
#include "packets.h"
class QTcpSocket;
class QByteArray;
class Server;
class ClosedClient : public QObject
{
Q_OBJECT
public:
explicit ClosedClient(QTcpSocket &socket, Server &server);
private slots:
void readyRead();
private:
void readPacket(packets::closed::serverbound::PacketType type, const QByteArray &buffer);
QTcpSocket &m_socket;
Server &m_server;
McDataStream m_dataStream;
qint32 m_packetSize{};
};

76
handshakingclient.cpp Normal file
View File

@@ -0,0 +1,76 @@
#include "handshakingclient.h"
#include <QTcpSocket>
#include "server.h"
#include "statusclient.h"
#include "loginclient.h"
HandshakingClient::HandshakingClient(QTcpSocket &socket, Server &server) :
QObject{&server}, m_socket{socket}, m_server{server}, m_dataStream{&m_socket}
{
m_socket.setParent(this);
connect(&m_socket, &QIODevice::readyRead, this, &HandshakingClient::readyRead);
connect(&m_socket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
}
void HandshakingClient::readyRead()
{
while(m_socket.bytesAvailable())
{
if(!m_packetSize)
{
m_packetSize = m_dataStream.readVar<qint32>();
qDebug() << "packet size" << m_packetSize;
}
if(m_socket.bytesAvailable() < m_packetSize)
{
qWarning() << "packet not fully available" << m_socket.bytesAvailable();
return;
}
qint32 bytesRead;
const auto type = m_dataStream.readVar<qint32>(bytesRead);
m_packetSize -= bytesRead;
const auto buffer = m_socket.read(m_packetSize);
Q_ASSERT(buffer.size() == m_packetSize);
m_packetSize = 0;
readPacket(packets::handshaking::serverbound::PacketType(type), buffer);
}
}
void HandshakingClient::readPacket(packets::handshaking::serverbound::PacketType type, const QByteArray &buffer)
{
McDataStream dataStream{const_cast<QByteArray *>(&buffer), QIODevice::ReadOnly};
switch(type)
{
using namespace packets::handshaking;
case serverbound::PacketType::Handshake:
{
qDebug() << type;
serverbound::Handshake packet{dataStream};
switch (packet.nextState)
{
using namespace serverbound;
case Handshake::SocketState::StatusState:
new StatusClient{m_socket, m_server};
break;
case Handshake::SocketState::LoginState:
new LoginClient{m_socket, m_server};
break;
default:
qCritical() << "client requested new state" << packet.nextState << "which is not allowed/invalid";
}
deleteLater();
break;
}
default:
qWarning() << "unknown packet type" << type;
}
}

32
handshakingclient.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include <QObject>
#include "mcdatastream.h"
#include "packets.h"
class QTcpSocket;
class QByteArray;
class Server;
class HandshakingClient : public QObject
{
Q_OBJECT
public:
explicit HandshakingClient(QTcpSocket &socket, Server &parent);
private slots:
void readyRead();
private:
void readPacket(packets::handshaking::serverbound::PacketType type, const QByteArray &buffer);
QTcpSocket &m_socket;
Server &m_server;
McDataStream m_dataStream;
qint32 m_packetSize{};
};

74
loginclient.cpp Normal file
View File

@@ -0,0 +1,74 @@
#include "loginclient.h"
#include <QTcpSocket>
#include "server.h"
#include "playclient.h"
LoginClient::LoginClient(QTcpSocket &socket, Server &server) :
QObject{&server}, m_socket{socket}, m_server{server}, m_dataStream{&m_socket}
{
m_socket.setParent(this);
connect(&m_socket, &QIODevice::readyRead, this, &LoginClient::readyRead);
connect(&m_socket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
}
void LoginClient::readyRead()
{
while(m_socket.bytesAvailable())
{
if(!m_packetSize)
{
m_packetSize = m_dataStream.readVar<qint32>();
qDebug() << "packet size" << m_packetSize;
}
if(m_socket.bytesAvailable() < m_packetSize)
{
qWarning() << "packet not fully available" << m_socket.bytesAvailable();
return;
}
qint32 bytesRead;
const auto type = m_dataStream.readVar<qint32>(bytesRead);
m_packetSize -= bytesRead;
const auto buffer = m_socket.read(m_packetSize);
Q_ASSERT(buffer.size() == m_packetSize);
m_packetSize = 0;
readPacket(packets::login::serverbound::PacketType(type), buffer);
}
}
void LoginClient::readPacket(packets::login::serverbound::PacketType type, const QByteArray &buffer)
{
McDataStream dataStream(const_cast<QByteArray *>(&buffer), QIODevice::ReadOnly);
switch(type)
{
using namespace packets::login;
case serverbound::PacketType::Login:
{
qDebug() << type;
QString name;
{
serverbound::Login packet{dataStream};
name = packet.name;
}
qDebug() << "Name" << name;
{
clientbound::LoginSuccess packet;
const auto uuid = QUuid::createUuid().toString();
packet.uuid = uuid.mid(1, uuid.length() - 2);
packet.username = name;
packet.serialize(m_dataStream);
}
new PlayClient{m_socket, m_server};
deleteLater();
break;
}
default:
qWarning() << "unknown packet type" << type;
}
}

32
loginclient.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include <QObject>
#include "mcdatastream.h"
#include "packets.h"
class QTcpSocket;
class QByteArray;
class Server;
class LoginClient : public QObject
{
Q_OBJECT
public:
explicit LoginClient(QTcpSocket &socket, Server &server);
private slots:
void readyRead();
private:
void readPacket(packets::login::serverbound::PacketType type, const QByteArray &buffer);
QTcpSocket &m_socket;
Server &m_server;
McDataStream m_dataStream;
qint32 m_packetSize{};
};

View File

@@ -1,11 +1,7 @@
#include <QCoreApplication>
#include <qlogging.h>
#include <QTcpServer>
#include <QList>
#include <QPointer>
#include <QTimer>
#include "client.h"
#include "server.h"
int main(int argc, char *argv[])
{
@@ -22,43 +18,7 @@ int main(int argc, char *argv[])
"%{function}(): "
"%{message}"));
QList<QPointer<Client>> clients;
QTimer timer;
timer.setInterval(100);
QObject::connect(&timer, &QTimer::timeout, [&clients](){
const auto now = QDateTime::currentDateTime();
for (auto iter = std::begin(clients); iter != std::end(clients); )
{
if ((*iter).isNull())
{
iter = clients.erase(iter);
continue;
}
auto &client = **iter;
if (client.state() == PlayState)
{
client.keepAlive();
client.sendChatMessage();
client.trialDisconnect();
}
iter++;
}
});
timer.start();
QTcpServer server;
QObject::connect(&server, &QTcpServer::newConnection, [&server,&clients](){
clients.append(new Client(server.nextPendingConnection()));
});
if(!server.listen(QHostAddress::Any, 25565))
qFatal("could not start listening %s", server.errorString().toUtf8().constData());
qDebug() << "started listening";
Server server;
return a.exec();
}

View File

@@ -1,5 +1,7 @@
#include "packets.h"
#include <QtGlobal>
#include "mcdatastream.h"
packets::handshaking::serverbound::Handshake::Handshake(McDataStream &stream)
@@ -79,6 +81,7 @@ packets::play::serverbound::InteractEntity::InteractEntity(McDataStream &stream)
targetX = stream.readFloat();
targetY = stream.readFloat();
targetZ = stream.readFloat();
[[fallthrough]];
case Interact:
hand = Hand(stream.readVar<qint32>());
}

View File

@@ -9,8 +9,6 @@
class McDataStream;
enum SocketState { HandshakingState, StatusState, LoginState, PlayState, ClosedState };
namespace packets {
namespace handshaking {
namespace serverbound {
@@ -20,16 +18,27 @@ namespace packets {
Q_ENUM_NS(PacketType)
struct Handshake {
Q_GADGET
public:
Handshake(McDataStream &stream);
qint32 protocolVersion;
QString serverAddress;
quint16 serverPort;
enum class SocketState { HandshakingState, StatusState, LoginState, PlayState, ClosedState };
Q_ENUM(SocketState)
SocketState nextState;
};
}
namespace clientbound {
Q_NAMESPACE
enum class PacketType {};
Q_ENUM_NS(PacketType)
}
}
@@ -220,4 +229,20 @@ namespace packets {
};
}
}
namespace closed {
namespace serverbound {
Q_NAMESPACE
enum class PacketType {};
Q_ENUM_NS(PacketType)
}
namespace clientbound {
Q_NAMESPACE
enum class PacketType {};
Q_ENUM_NS(PacketType)
}
}
}

186
playclient.cpp Normal file
View File

@@ -0,0 +1,186 @@
#include "playclient.h"
#include <QTcpSocket>
#include <QDateTime>
#include "server.h"
#include "closedclient.h"
PlayClient::PlayClient(QTcpSocket &socket, Server &server) :
QObject{&server}, m_socket{socket}, m_server{server}, m_dataStream{&m_socket}
{
m_server.add(*this);
m_socket.setParent(this);
connect(&m_socket, &QIODevice::readyRead, this, &PlayClient::readyRead);
connect(&m_socket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
{
packets::play::clientbound::JoinGame packet;
packet.entityid = 1;
packet.gamemode = packets::play::clientbound::JoinGame::Creative;
packet.dimension = packets::play::clientbound::JoinGame::Overworld;
packet.difficulty = 2;
packet.maxPlayers = 255;
packet.levelType = QStringLiteral("default");
packet.reducedDebugInfo = false;
packet.serialize(m_dataStream);
}
{
packets::play::clientbound::PluginMessage packet;
packet.channel = QStringLiteral("minecraft:brand");
packet.data = QByteArrayLiteral("bullshit");
packet.serialize(m_dataStream);
}
{
packets::play::clientbound::ServerDifficulty packet;
packet.difficulty = 2;
packet.serialize(m_dataStream);
}
{
packets::play::clientbound::SpawnPosition packet;
packet.location = std::make_tuple(100, 64, 100);
packet.serialize(m_dataStream);
}
{
packets::play::clientbound::PlayerAbilities packet;
packet.flags = 0x0F;
packet.flyingSpeed = 1.;
packet.fieldOfViewModifier = 60.;
packet.serialize(m_dataStream);
}
}
PlayClient::~PlayClient()
{
m_server.remove(*this);
}
void PlayClient::keepAlive()
{
const auto now = QDateTime::currentDateTime();
if (!m_lastKeepAliveSent.isValid() || m_lastKeepAliveSent.secsTo(now) >= 1)
{
packets::play::clientbound::KeepAlive packet;
packet.keepAliveId = 0;
packet.serialize(m_dataStream);
m_lastKeepAliveSent = now;
}
}
void PlayClient::sendChatMessage()
{
const auto now = QDateTime::currentDateTime();
if (!m_lastChatMessage.isValid() || m_lastChatMessage.secsTo(now) >= 2)
{
packets::play::clientbound::ChatMessage packet;
packet.jsonData = "{"
"\"text\": \"Chat message\", "
"\"bold\": \"true\" "
"}";
packet.position = packets::play::clientbound::ChatMessage::Chat;
packet.serialize(m_dataStream);
m_lastChatMessage = now;
}
}
void PlayClient::trialDisconnect()
{
const auto now = QDateTime::currentDateTime();
if (m_connectedSince.secsTo(now) >= 20)
{
packets::play::clientbound::Disconnect packet;
packet.reason = "{"
"\"text\": \"Your trial has ended.\", "
"\"bold\": \"true\" "
"}";
packet.serialize(m_dataStream);
m_socket.flush();
new ClosedClient{m_socket, m_server};
deleteLater();
}
}
void PlayClient::readyRead()
{
while(m_socket.bytesAvailable())
{
if(!m_packetSize)
{
m_packetSize = m_dataStream.readVar<qint32>();
qDebug() << "packet size" << m_packetSize;
}
if(m_socket.bytesAvailable() < m_packetSize)
{
qWarning() << "packet not fully available" << m_socket.bytesAvailable();
return;
}
qint32 bytesRead;
const auto type = m_dataStream.readVar<qint32>(bytesRead);
m_packetSize -= bytesRead;
const auto buffer = m_socket.read(m_packetSize);
Q_ASSERT(buffer.size() == m_packetSize);
m_packetSize = 0;
readPacket(packets::play::serverbound::PacketType(type), buffer);
}
}
void PlayClient::readPacket(packets::play::serverbound::PacketType type, const QByteArray &buffer)
{
McDataStream dataStream(const_cast<QByteArray *>(&buffer), QIODevice::ReadOnly);
switch(type)
{
using namespace packets::play;
case serverbound::PacketType::ClientSettings:
{
qDebug() << type;
{
serverbound::ClientSettings packet{dataStream};
qDebug() << "locale" << packet.locale;
qDebug() << "viewDistance" << packet.viewDistance;
qDebug() << "chatMode" << packet.chatMode;
qDebug() << "chatColors" << packet.chatColors;
qDebug() << "displayedSkinParts" << packet.displayedSkinParts;
qDebug() << "mainHand" << packet.mainHand;
}
{
clientbound::PlayerPositionAndLook packet;
packet.x = 50.;
packet.y = 64.;
packet.z = 50.;
packet.yaw = 0.;
packet.pitch = 0.;
packet.flags = 0;
packet.teleportId = 0;
packet.serialize(m_dataStream);
}
break;
}
case serverbound::PacketType::InteractEntity:
{
qDebug() << type;
serverbound::InteractEntity packet{dataStream};
qDebug() << "entityId" << packet.entityId;
qDebug() << "type" << packet.type;
// qDebug() << "targetX" << packet.targetX;
// qDebug() << "targetY" << packet.targetY;
// qDebug() << "targetZ" << packet.targetZ;
// qDebug() << "hand" << packet.hand;
break;
}
case serverbound::PacketType::PluginMessage:
{
qDebug() << type;
serverbound::PluginMessage packet{dataStream};
qDebug() << "channel" << packet.channel;
break;
}
default:
qWarning() << "unknown packet type" << type;
}
}

42
playclient.h Normal file
View File

@@ -0,0 +1,42 @@
#pragma once
#include <QObject>
#include "mcdatastream.h"
#include "packets.h"
class QTcpSocket;
class QByteArray;
class Server;
class PlayClient : public QObject
{
Q_OBJECT
public:
explicit PlayClient(QTcpSocket &socket, Server &server);
~PlayClient() override;
void keepAlive();
void sendChatMessage();
void trialDisconnect();
private slots:
void readyRead();
private:
void readPacket(packets::play::serverbound::PacketType type, const QByteArray &buffer);
QTcpSocket &m_socket;
Server &m_server;
McDataStream m_dataStream;
qint32 m_packetSize{};
const QDateTime m_connectedSince{QDateTime::currentDateTime()};
QDateTime m_lastKeepAliveSent;
QDateTime m_lastKeepAliveReceived;
QDateTime m_lastChatMessage;
};

47
server.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include "server.h"
#include <QDateTime>
#include "playclient.h"
#include "handshakingclient.h"
Server::Server(QObject *parent) :
QObject{parent}
{
m_timer.setInterval(100);
connect(&m_timer, &QTimer::timeout, this, &Server::timeout);
m_timer.start();
connect(&m_server, &QTcpServer::newConnection, this, &Server::newConnection);
if(!m_server.listen(QHostAddress::Any, 25565))
qFatal("could not start listening %s", m_server.errorString().toUtf8().constData());
}
void Server::add(PlayClient &playClient)
{
m_playClients.insert(&playClient);
}
void Server::remove(PlayClient &playClient)
{
m_playClients.erase(&playClient);
}
void Server::timeout()
{
for (auto client : m_playClients)
{
client->keepAlive();
client->sendChatMessage();
client->trialDisconnect();
}
}
void Server::newConnection()
{
auto * const connection = m_server.nextPendingConnection();
if (connection)
new HandshakingClient{*connection, *this};
//clients.push_back();
}

31
server.h Normal file
View File

@@ -0,0 +1,31 @@
#pragma once
#include <QObject>
#include <QTimer>
#include <QTcpServer>
#include <QPointer>
#include <set>
class PlayClient;
class Server : public QObject
{
Q_OBJECT
public:
Server(QObject *parent = nullptr);
void add(PlayClient &playClient);
void remove(PlayClient &playClient);
private slots:
void timeout();
void newConnection();
private:
QTimer m_timer;
QTcpServer m_server;
std::set<PlayClient*> m_playClients;
};

View File

@@ -1,69 +1,21 @@
#include "client.h"
#include "statusclient.h"
#include <QDebug>
#include <QTcpSocket>
#include <QUuid>
#include <QTimer>
Client::Client(QTcpSocket *socket, QObject *parent) :
QObject(parent), m_socket(socket), m_dataStream(m_socket),
m_packetSize(0), m_state(HandshakingState), m_connectedSince(QDateTime::currentDateTime())
#include "server.h"
StatusClient::StatusClient(QTcpSocket &socket, Server &server) :
QObject{&server}, m_socket{socket}, m_server{server}, m_dataStream{&m_socket}
{
m_socket->setParent(this);
m_socket.setParent(this);
connect(m_socket, &QIODevice::readyRead, this, &Client::readyRead);
connect(m_socket, &QAbstractSocket::disconnected, this, &Client::disconnected);
qDebug() << m_socket->peerPort();
connect(&m_socket, &QIODevice::readyRead, this, &StatusClient::readyRead);
connect(&m_socket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
}
void Client::keepAlive()
void StatusClient::readyRead()
{
const auto now = QDateTime::currentDateTime();
if (!m_lastKeepAliveSent.isValid() || m_lastKeepAliveSent.secsTo(now) >= 1)
{
packets::play::clientbound::KeepAlive packet;
packet.keepAliveId = 0;
packet.serialize(m_dataStream);
m_lastKeepAliveSent = now;
}
}
void Client::sendChatMessage()
{
const auto now = QDateTime::currentDateTime();
if (!m_lastChatMessage.isValid() || m_lastChatMessage.secsTo(now) >= 2)
{
packets::play::clientbound::ChatMessage packet;
packet.jsonData = "{"
"\"text\": \"Chat message\", "
"\"bold\": \"true\" "
"}";
packet.position = packets::play::clientbound::ChatMessage::Chat;
packet.serialize(m_dataStream);
m_lastChatMessage = now;
}
}
void Client::trialDisconnect()
{
const auto now = QDateTime::currentDateTime();
if (m_connectedSince.secsTo(now) >= 20)
{
packets::play::clientbound::Disconnect packet;
packet.reason = "{"
"\"text\": \"Your trial has ended.\", "
"\"bold\": \"true\" "
"}";
packet.serialize(m_dataStream);
m_socket->flush();
deleteLater();
}
}
void Client::readyRead()
{
while(m_socket->bytesAvailable())
while(m_socket.bytesAvailable())
{
if(!m_packetSize)
{
@@ -71,69 +23,25 @@ void Client::readyRead()
qDebug() << "packet size" << m_packetSize;
}
if(m_socket->bytesAvailable() < m_packetSize)
if(m_socket.bytesAvailable() < m_packetSize)
{
qWarning() << "packet not fully available" << m_socket->bytesAvailable();
qWarning() << "packet not fully available" << m_socket.bytesAvailable();
return;
}
qint32 bytesRead;
const auto type = m_dataStream.readVar<qint32>(bytesRead);
m_packetSize -= bytesRead;
const auto buffer = m_socket->read(m_packetSize);
const auto buffer = m_socket.read(m_packetSize);
Q_ASSERT(buffer.size() == m_packetSize);
m_packetSize = 0;
switch(m_state)
{
case HandshakingState:
readPacketHandshaking(packets::handshaking::serverbound::PacketType(type), buffer);
break;
case StatusState:
readPacketStatus(packets::status::serverbound::PacketType(type), buffer);
break;
case LoginState:
readPacketLogin(packets::login::serverbound::PacketType(type), buffer);
break;
case PlayState:
readPacketPlay(packets::play::serverbound::PacketType(type), buffer);
break;
default:
qWarning() << "unhandled state" << m_state << type << buffer;
}
readPacket(packets::status::serverbound::PacketType(type), buffer);
}
}
void Client::disconnected()
void StatusClient::readPacket(packets::status::serverbound::PacketType type, const QByteArray &buffer)
{
qDebug() << m_socket->peerPort();
deleteLater();
}
void Client::readPacketHandshaking(packets::handshaking::serverbound::PacketType type, const QByteArray &buffer)
{
qDebug() << type;
McDataStream dataStream(const_cast<QByteArray *>(&buffer), QIODevice::ReadOnly);
switch(type)
{
using namespace packets::handshaking;
case serverbound::PacketType::Handshake:
{
serverbound::Handshake packet(dataStream);
m_state = packet.nextState;
break;
}
default:
qWarning() << "unknown type!";
}
}
void Client::readPacketStatus(const packets::status::serverbound::PacketType type, const QByteArray &buffer)
{
qDebug() << type;
McDataStream dataStream(const_cast<QByteArray *>(&buffer), QIODevice::ReadOnly);
switch(type)
@@ -141,8 +49,9 @@ void Client::readPacketStatus(const packets::status::serverbound::PacketType typ
using namespace packets::status;
case serverbound::PacketType::Request:
{
qDebug() << type;
{
serverbound::Request packet(dataStream);
serverbound::Request packet{dataStream};
}
{
clientbound::Response packet;
@@ -173,9 +82,10 @@ void Client::readPacketStatus(const packets::status::serverbound::PacketType typ
}
case serverbound::PacketType::Ping:
{
qDebug() << type;
qint64 payload;
{
serverbound::Ping packet(dataStream);
serverbound::Ping packet{dataStream};
payload = packet.payload;
}
{
@@ -186,127 +96,6 @@ void Client::readPacketStatus(const packets::status::serverbound::PacketType typ
break;
}
default:
qWarning() << "unknown type!";
}
}
void Client::readPacketLogin(const packets::login::serverbound::PacketType type, const QByteArray &buffer)
{
qDebug() << type;
McDataStream dataStream(const_cast<QByteArray *>(&buffer), QIODevice::ReadOnly);
switch(type)
{
using namespace packets::login;
case serverbound::PacketType::Login:
{
QString name;
{
serverbound::Login packet(dataStream);
name = packet.name;
}
qDebug() << "Name" << name;
{
clientbound::LoginSuccess packet;
const auto uuid = QUuid::createUuid().toString();
packet.uuid = uuid.mid(1, uuid.length() - 2);
packet.username = name;
packet.serialize(m_dataStream);
}
m_state = PlayState;
{
packets::play::clientbound::JoinGame packet;
packet.entityid = 1;
packet.gamemode = packets::play::clientbound::JoinGame::Creative;
packet.dimension = packets::play::clientbound::JoinGame::Overworld;
packet.difficulty = 2;
packet.maxPlayers = 255;
packet.levelType = QStringLiteral("default");
packet.reducedDebugInfo = false;
packet.serialize(m_dataStream);
}
{
packets::play::clientbound::PluginMessage packet;
packet.channel = QStringLiteral("minecraft:brand");
packet.data = QByteArrayLiteral("bullshit");
packet.serialize(m_dataStream);
}
{
packets::play::clientbound::ServerDifficulty packet;
packet.difficulty = 2;
packet.serialize(m_dataStream);
}
{
packets::play::clientbound::SpawnPosition packet;
packet.location = std::make_tuple(100, 64, 100);
packet.serialize(m_dataStream);
}
{
packets::play::clientbound::PlayerAbilities packet;
packet.flags = 0x0F;
packet.flyingSpeed = 1.;
packet.fieldOfViewModifier = 60.;
packet.serialize(m_dataStream);
}
break;
}
default:
qWarning() << "unknown type!";
}
}
void Client::readPacketPlay(const packets::play::serverbound::PacketType type, const QByteArray &buffer)
{
qDebug() << type;
McDataStream dataStream(const_cast<QByteArray *>(&buffer), QIODevice::ReadOnly);
switch(type)
{
using namespace packets::play;
case serverbound::PacketType::ClientSettings:
{
{
serverbound::ClientSettings packet(dataStream);
qDebug() << "locale" << packet.locale;
qDebug() << "viewDistance" << packet.viewDistance;
qDebug() << "chatMode" << packet.chatMode;
qDebug() << "chatColors" << packet.chatColors;
qDebug() << "displayedSkinParts" << packet.displayedSkinParts;
qDebug() << "mainHand" << packet.mainHand;
}
{
clientbound::PlayerPositionAndLook packet;
packet.x = 50.;
packet.y = 64.;
packet.z = 50.;
packet.yaw = 0.;
packet.pitch = 0.;
packet.flags = 0;
packet.teleportId = 0;
packet.serialize(m_dataStream);
}
break;
}
case serverbound::PacketType::InteractEntity:
{
serverbound::InteractEntity packet(dataStream);
qDebug() << "entityId" << packet.entityId;
qDebug() << "type" << packet.type;
// qDebug() << "targetX" << packet.targetX;
// qDebug() << "targetY" << packet.targetY;
// qDebug() << "targetZ" << packet.targetZ;
// qDebug() << "hand" << packet.hand;
break;
}
case serverbound::PacketType::PluginMessage:
{
serverbound::PluginMessage packet(dataStream);
qDebug() << "channel" << packet.channel;
break;
}
default:
qWarning() << "unknown type!";
qWarning() << "unknown packet type" << type;
}
}

32
statusclient.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include <QObject>
#include "mcdatastream.h"
#include "packets.h"
class QTcpSocket;
class QByteArray;
class Server;
class StatusClient : public QObject
{
Q_OBJECT
public:
explicit StatusClient(QTcpSocket &socket, Server &server);
private slots:
void readyRead();
private:
void readPacket(packets::status::serverbound::PacketType type, const QByteArray &buffer);
QTcpSocket &m_socket;
Server &m_server;
McDataStream m_dataStream;
qint32 m_packetSize{};
};