Imported existing sources
This commit is contained in:
15
DbMinecraft.pro
Normal file
15
DbMinecraft.pro
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
QT = core network
|
||||||
|
|
||||||
|
CONFIG += c++1z
|
||||||
|
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS QT_DISABLE_DEPRECATED_BEFORE=0x060000
|
||||||
|
|
||||||
|
SOURCES += main.cpp \
|
||||||
|
client.cpp \
|
||||||
|
mcdatastream.cpp \
|
||||||
|
packets.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
client.h \
|
||||||
|
mcdatastream.h \
|
||||||
|
packets.h
|
257
client.cpp
Normal file
257
client.cpp
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
#include "client.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_socket->setParent(this);
|
||||||
|
|
||||||
|
connect(m_socket, &QIODevice::readyRead, this, &Client::readyRead);
|
||||||
|
connect(m_socket, &QAbstractSocket::disconnected, this, &Client::disconnected);
|
||||||
|
|
||||||
|
qDebug() << m_socket->peerPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::disconnected()
|
||||||
|
{
|
||||||
|
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::PacketHandshake:
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
using namespace packets::status;
|
||||||
|
case serverbound::PacketRequest:
|
||||||
|
{
|
||||||
|
{
|
||||||
|
serverbound::Request packet(dataStream);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
clientbound::Response packet;
|
||||||
|
packet.jsonResponse =
|
||||||
|
"{"
|
||||||
|
" \"version\": {"
|
||||||
|
" \"name\": \"1.13.1\","
|
||||||
|
" \"protocol\": 401"
|
||||||
|
" },"
|
||||||
|
" \"players\": {"
|
||||||
|
" \"max\": 1000,"
|
||||||
|
" \"online\": 2000,"
|
||||||
|
" \"sample\": ["
|
||||||
|
" {"
|
||||||
|
" \"name\": \"0xFEEDC0DE64\","
|
||||||
|
" \"id\": \"6ebf7396-b6da-40b1-b7d9-9b7961450d5a\""
|
||||||
|
" }"
|
||||||
|
" ]"
|
||||||
|
" }, "
|
||||||
|
" \"description\": {"
|
||||||
|
" \"text\": \"Mein monster server in C++\""
|
||||||
|
" },"
|
||||||
|
" \"favicon\": \"\""
|
||||||
|
"}";
|
||||||
|
packet.serialize(m_dataStream);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case serverbound::PacketPing:
|
||||||
|
{
|
||||||
|
qint64 payload;
|
||||||
|
{
|
||||||
|
serverbound::Ping packet(dataStream);
|
||||||
|
payload = packet.payload;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
clientbound::Pong packet;
|
||||||
|
packet.payload = payload;
|
||||||
|
packet.serialize(m_dataStream);
|
||||||
|
}
|
||||||
|
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::PacketLogin:
|
||||||
|
{
|
||||||
|
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 = 0;
|
||||||
|
packet.dimension = 0;
|
||||||
|
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::PacketClientSettings:
|
||||||
|
{
|
||||||
|
{
|
||||||
|
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::PacketPluginMessage:
|
||||||
|
{
|
||||||
|
serverbound::PluginMessage packet(dataStream);
|
||||||
|
qDebug() << "channel" << packet.channel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
qWarning() << "unknown type!";
|
||||||
|
}
|
||||||
|
}
|
33
client.h
Normal file
33
client.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "mcdatastream.h"
|
||||||
|
#include "packets.h"
|
||||||
|
|
||||||
|
class QTcpSocket;
|
||||||
|
|
||||||
|
class Client : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Client(QTcpSocket *socket, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
34
main.cpp
Normal file
34
main.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include <QCoreApplication>
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <QTcpServer>
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
|
qSetMessagePattern(QStringLiteral("%{time dd.MM.yyyy HH:mm:ss.zzz} "
|
||||||
|
"["
|
||||||
|
"%{if-debug}D%{endif}"
|
||||||
|
"%{if-info}I%{endif}"
|
||||||
|
"%{if-warning}W%{endif}"
|
||||||
|
"%{if-critical}C%{endif}"
|
||||||
|
"%{if-fatal}F%{endif}"
|
||||||
|
"] "
|
||||||
|
"%{function}(): "
|
||||||
|
"%{message}"));
|
||||||
|
|
||||||
|
QTcpServer server;
|
||||||
|
|
||||||
|
QObject::connect(&server, &QTcpServer::newConnection, [&server](){
|
||||||
|
new Client(server.nextPendingConnection());
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!server.listen(QHostAddress::Any, 25565))
|
||||||
|
qFatal("could not start listening %s", server.errorString().toUtf8().constData());
|
||||||
|
|
||||||
|
qDebug() << "started listening";
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
173
mcdatastream.cpp
Normal file
173
mcdatastream.cpp
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
#include "mcdatastream.h"
|
||||||
|
|
||||||
|
#include <QPoint>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
McDataStream::McDataStream() :
|
||||||
|
QDataStream()
|
||||||
|
{
|
||||||
|
setByteOrder(QDataStream::BigEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
McDataStream::McDataStream(QIODevice *device) :
|
||||||
|
QDataStream(device)
|
||||||
|
{
|
||||||
|
setByteOrder(QDataStream::BigEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
McDataStream::McDataStream(QByteArray *byteArray, QIODevice::OpenMode flags) :
|
||||||
|
QDataStream(byteArray, flags)
|
||||||
|
{
|
||||||
|
setByteOrder(QDataStream::BigEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
McDataStream::McDataStream(const QByteArray &byteArray) :
|
||||||
|
QDataStream(byteArray)
|
||||||
|
{
|
||||||
|
setByteOrder(QDataStream::BigEndian);
|
||||||
|
}
|
||||||
|
|
||||||
|
McDataStream::Position McDataStream::readPosition()
|
||||||
|
{
|
||||||
|
quint64 val;
|
||||||
|
*this >> val;
|
||||||
|
const qint32 x = val >> 38;
|
||||||
|
const qint16 y = (val >> 26) & 0xFFF;
|
||||||
|
const qint32 z = val << 38 >> 38;
|
||||||
|
return std::make_tuple(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void McDataStream::writePosition(const Position &position)
|
||||||
|
{
|
||||||
|
const quint64 val = ((quint64(std::get<0>(position)) & 0x3FFFFFF) << 38) |
|
||||||
|
((quint64(std::get<1>(position)) & 0xFFF) << 26) |
|
||||||
|
(quint64(std::get<2>(position)) & 0x3FFFFFF);
|
||||||
|
*this << val;
|
||||||
|
}
|
||||||
|
|
||||||
|
float McDataStream::readFloat()
|
||||||
|
{
|
||||||
|
const auto precision = floatingPointPrecision();
|
||||||
|
setFloatingPointPrecision(SinglePrecision);
|
||||||
|
float value;
|
||||||
|
*this >> value;
|
||||||
|
setFloatingPointPrecision(precision);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void McDataStream::writeFloat(float value)
|
||||||
|
{
|
||||||
|
const auto precision = floatingPointPrecision();
|
||||||
|
setFloatingPointPrecision(SinglePrecision);
|
||||||
|
*this << value;
|
||||||
|
setFloatingPointPrecision(precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
float McDataStream::readDouble()
|
||||||
|
{
|
||||||
|
const auto precision = floatingPointPrecision();
|
||||||
|
setFloatingPointPrecision(DoublePrecision);
|
||||||
|
double value;
|
||||||
|
*this >> value;
|
||||||
|
setFloatingPointPrecision(precision);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void McDataStream::writeDouble(double value)
|
||||||
|
{
|
||||||
|
const auto precision = floatingPointPrecision();
|
||||||
|
setFloatingPointPrecision(DoublePrecision);
|
||||||
|
*this << value;
|
||||||
|
setFloatingPointPrecision(precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
qint32 McDataStream::readVar<qint32>(qint32 &bytesRead)
|
||||||
|
{
|
||||||
|
bytesRead = 0;
|
||||||
|
qint32 result = 0;
|
||||||
|
qint8 read;
|
||||||
|
do {
|
||||||
|
*this >> read;
|
||||||
|
qint32 value = read & 0b01111111;
|
||||||
|
result |= value << (7 * bytesRead);
|
||||||
|
|
||||||
|
bytesRead++;
|
||||||
|
if (bytesRead > 5) {
|
||||||
|
qFatal("VarInt is too big");
|
||||||
|
}
|
||||||
|
} while ((read & 0b10000000) != 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
qint64 McDataStream::readVar<qint64>(qint32 &bytesRead)
|
||||||
|
{
|
||||||
|
bytesRead = 0;
|
||||||
|
qint64 result = 0;
|
||||||
|
qint8 read;
|
||||||
|
do {
|
||||||
|
*this >> read;
|
||||||
|
qint32 value = read & 0b01111111;
|
||||||
|
result |= value << (7 * bytesRead);
|
||||||
|
|
||||||
|
bytesRead++;
|
||||||
|
if (bytesRead > 10) {
|
||||||
|
qFatal("VarInt is too big");
|
||||||
|
}
|
||||||
|
} while ((read & 0b10000000) != 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
QString McDataStream::readVar<QString>(qint32 &bytesRead)
|
||||||
|
{
|
||||||
|
const auto length = readVar<qint32>(bytesRead);
|
||||||
|
|
||||||
|
auto data = std::unique_ptr<char[]>(new char[length]);
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto rawLength = readRawData(data.get(), length);
|
||||||
|
bytesRead += rawLength;
|
||||||
|
Q_ASSERT(length == rawLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString::fromUtf8(data.get(), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void McDataStream::writeVar(qint32 value)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
qint8 temp = value & 0b01111111;
|
||||||
|
value >>= 7;
|
||||||
|
if (value != 0) {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
*this << temp;
|
||||||
|
} while (value != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void McDataStream::writeVar(qint64 value)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
qint8 temp = value & 0b01111111;
|
||||||
|
value >>= 7;
|
||||||
|
if (value != 0) {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
*this << temp;
|
||||||
|
} while (value != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void McDataStream::writeVar(QString value)
|
||||||
|
{
|
||||||
|
const auto bytes = value.toUtf8();
|
||||||
|
writeVar<qint32>(bytes.length());
|
||||||
|
writeRawData(bytes.constData(), bytes.length());
|
||||||
|
}
|
58
mcdatastream.h
Normal file
58
mcdatastream.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
class McDataStream : public QDataStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
McDataStream();
|
||||||
|
explicit McDataStream(QIODevice *device);
|
||||||
|
McDataStream(QByteArray *byteArray, QIODevice::OpenMode flags);
|
||||||
|
McDataStream(const QByteArray &byteArray);
|
||||||
|
|
||||||
|
typedef std::tuple<qint32, qint16, qint32> Position;
|
||||||
|
Position readPosition();
|
||||||
|
void writePosition(const Position &position);
|
||||||
|
|
||||||
|
float readFloat();
|
||||||
|
void writeFloat(float value);
|
||||||
|
|
||||||
|
float readDouble();
|
||||||
|
void writeDouble(double value);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T readVar();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T readVar(qint32 &bytesRead);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void writeVar(T value);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T McDataStream::readVar()
|
||||||
|
{
|
||||||
|
qint32 bytesRead;
|
||||||
|
return readVar<T>(bytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
qint32 McDataStream::readVar<qint32>(qint32 &bytesRead);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
qint64 McDataStream::readVar<qint64>(qint32 &bytesRead);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
QString McDataStream::readVar<QString>(qint32 &bytesRead);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void McDataStream::writeVar(qint32 value);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void McDataStream::writeVar(qint64 value);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void McDataStream::writeVar(QString value);
|
150
packets.cpp
Normal file
150
packets.cpp
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#include "packets.h"
|
||||||
|
|
||||||
|
#include "mcdatastream.h"
|
||||||
|
|
||||||
|
packets::handshaking::serverbound::Handshake::Handshake(McDataStream &stream)
|
||||||
|
{
|
||||||
|
protocolVersion = stream.readVar<qint32>();
|
||||||
|
serverAddress = stream.readVar<QString>();
|
||||||
|
stream >> serverPort;
|
||||||
|
const auto socketState = stream.readVar<qint32>();
|
||||||
|
Q_ASSERT(socketState == 1 || socketState == 2);
|
||||||
|
nextState = SocketState(socketState);
|
||||||
|
}
|
||||||
|
|
||||||
|
packets::status::serverbound::Request::Request(McDataStream &stream)
|
||||||
|
{
|
||||||
|
Q_UNUSED(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
packets::status::serverbound::Ping::Ping(McDataStream &stream)
|
||||||
|
{
|
||||||
|
stream >> payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::status::clientbound::Response::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketResponse);
|
||||||
|
tempStream.writeVar<QString>(jsonResponse);
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::status::clientbound::Pong::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketPong);
|
||||||
|
tempStream << payload;
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
packets::login::serverbound::Login::Login(McDataStream &stream)
|
||||||
|
{
|
||||||
|
name = stream.readVar<QString>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::login::clientbound::LoginSuccess::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketLoginSuccess);
|
||||||
|
tempStream.writeVar<QString>(uuid);
|
||||||
|
tempStream.writeVar<QString>(username);
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
packets::play::serverbound::ClientSettings::ClientSettings(McDataStream &stream)
|
||||||
|
{
|
||||||
|
locale = stream.readVar<QString>();
|
||||||
|
stream >> viewDistance;
|
||||||
|
chatMode = stream.readVar<qint32>();
|
||||||
|
stream >> chatColors
|
||||||
|
>> displayedSkinParts;
|
||||||
|
mainHand = stream.readVar<qint32>();
|
||||||
|
}
|
||||||
|
|
||||||
|
packets::play::serverbound::PluginMessage::PluginMessage(McDataStream &stream)
|
||||||
|
{
|
||||||
|
channel = stream.readVar<QString>();
|
||||||
|
//TODO read to end of buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::play::clientbound::ServerDifficulty::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketServerDifficulty);
|
||||||
|
tempStream << difficulty;
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::play::clientbound::PluginMessage::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketPluginMessage);
|
||||||
|
tempStream.writeVar<QString>(channel);
|
||||||
|
buffer.append(data);
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::play::clientbound::JoinGame::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketJoinGame);
|
||||||
|
tempStream << entityid
|
||||||
|
<< gamemode
|
||||||
|
<< dimension
|
||||||
|
<< difficulty
|
||||||
|
<< maxPlayers;
|
||||||
|
tempStream.writeVar<QString>(levelType);
|
||||||
|
tempStream << reducedDebugInfo;
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::play::clientbound::PlayerAbilities::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketPlayerAbilities);
|
||||||
|
tempStream << flags;
|
||||||
|
tempStream.writeFloat(flyingSpeed);
|
||||||
|
tempStream.writeFloat(fieldOfViewModifier);
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::play::clientbound::PlayerPositionAndLook::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketPlayerPositionAndLook);
|
||||||
|
tempStream.writeDouble(x);
|
||||||
|
tempStream.writeDouble(y);
|
||||||
|
tempStream.writeDouble(z);
|
||||||
|
tempStream.writeFloat(yaw);
|
||||||
|
tempStream.writeFloat(pitch);
|
||||||
|
tempStream << flags;
|
||||||
|
tempStream.writeVar<qint32>(teleportId);
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void packets::play::clientbound::SpawnPosition::serialize(McDataStream &stream)
|
||||||
|
{
|
||||||
|
QByteArray buffer;
|
||||||
|
McDataStream tempStream(&buffer, QIODevice::WriteOnly);
|
||||||
|
tempStream.writeVar<qint32>(PacketSpawnPosition);
|
||||||
|
tempStream.writePosition(location);
|
||||||
|
stream.writeVar<qint32>(buffer.length());
|
||||||
|
stream.writeRawData(buffer.constData(), buffer.length());
|
||||||
|
}
|
165
packets.h
Normal file
165
packets.h
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
class McDataStream;
|
||||||
|
|
||||||
|
enum SocketState { HandshakingState, StatusState, LoginState, PlayState, ClosedState };
|
||||||
|
|
||||||
|
namespace packets {
|
||||||
|
namespace handshaking {
|
||||||
|
namespace serverbound {
|
||||||
|
enum PacketType { PacketHandshake };
|
||||||
|
|
||||||
|
struct Handshake {
|
||||||
|
Handshake(McDataStream &stream);
|
||||||
|
|
||||||
|
qint32 protocolVersion;
|
||||||
|
QString serverAddress;
|
||||||
|
quint16 serverPort;
|
||||||
|
SocketState nextState;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace clientbound {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace status {
|
||||||
|
namespace serverbound {
|
||||||
|
enum PacketType { PacketRequest, PacketPing };
|
||||||
|
|
||||||
|
struct Request {
|
||||||
|
Request(McDataStream &stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ping {
|
||||||
|
Ping(McDataStream &stream);
|
||||||
|
|
||||||
|
qint64 payload;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace clientbound {
|
||||||
|
enum PacketType { PacketResponse, PacketPong };
|
||||||
|
|
||||||
|
struct Response {
|
||||||
|
QString jsonResponse;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Pong {
|
||||||
|
qint64 payload;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace login {
|
||||||
|
namespace serverbound {
|
||||||
|
enum PacketType { PacketLogin };
|
||||||
|
|
||||||
|
struct Login {
|
||||||
|
Login(McDataStream &stream);
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace clientbound {
|
||||||
|
enum PacketType { PacketLoginSuccess = 0x02 };
|
||||||
|
|
||||||
|
struct LoginSuccess {
|
||||||
|
QString uuid;
|
||||||
|
QString username;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace play {
|
||||||
|
namespace serverbound {
|
||||||
|
enum PacketType { PacketClientSettings = 0x04, PacketPluginMessage = 0x0A };
|
||||||
|
|
||||||
|
struct ClientSettings {
|
||||||
|
ClientSettings(McDataStream &stream);
|
||||||
|
|
||||||
|
QString locale;
|
||||||
|
qint8 viewDistance;
|
||||||
|
qint32 chatMode;
|
||||||
|
bool chatColors;
|
||||||
|
quint8 displayedSkinParts;
|
||||||
|
qint32 mainHand;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PluginMessage {
|
||||||
|
PluginMessage(McDataStream &stream);
|
||||||
|
|
||||||
|
QString channel;
|
||||||
|
QByteArray data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace clientbound {
|
||||||
|
enum PacketType { PacketServerDifficulty = 0x0D, PacketPluginMessage = 0x19, PacketJoinGame = 0x25, PacketPlayerAbilities = 0x2E, PacketPlayerPositionAndLook = 0x32,
|
||||||
|
PacketSpawnPosition = 0x49 };
|
||||||
|
|
||||||
|
struct ServerDifficulty {
|
||||||
|
quint8 difficulty;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PluginMessage {
|
||||||
|
QString channel;
|
||||||
|
QByteArray data;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JoinGame {
|
||||||
|
qint32 entityid;
|
||||||
|
quint8 gamemode;
|
||||||
|
qint32 dimension;
|
||||||
|
quint8 difficulty;
|
||||||
|
quint8 maxPlayers;
|
||||||
|
QString levelType;
|
||||||
|
bool reducedDebugInfo;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlayerAbilities {
|
||||||
|
qint8 flags;
|
||||||
|
float flyingSpeed;
|
||||||
|
float fieldOfViewModifier;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlayerPositionAndLook {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
float yaw;
|
||||||
|
float pitch;
|
||||||
|
qint8 flags;
|
||||||
|
qint32 teleportId;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SpawnPosition {
|
||||||
|
std::tuple<qint32, qint16, qint32> location;
|
||||||
|
|
||||||
|
void serialize(McDataStream &stream);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user