summaryrefslogtreecommitdiffstats
path: root/NetworkClient.cpp
blob: d6835e0e1f5a9b3f0a9878ed378acd39bbc0ac8d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "NetworkClient.hpp"
#include "PacketParser.hpp"
#include "PacketBuilder.hpp"
#include "json.hpp"

ServerInfo NetworkClient::ServerPing(std::string address, unsigned short port) {
    ServerInfo info;
    Network network(address, port);
    Packet packet_handshake = PacketBuilder::CHandshaking0x00(316, address, port, 1);
    network.SendPacket(packet_handshake);
    Packet packet_request(0);
    network.SendPacket(packet_request);
    Packet packet_response = network.ReceivePacket();
    PacketParser::Parse(packet_response, Login);
    //std::string json = static_cast<FieldString *>(packet_response_parsed.GetFieldById(0))->GetValue();
    std::string json = packet_response.GetField(0).GetString();
    try {
        nlohmann::json j = nlohmann::json::parse(json);
        info.protocol = j["version"]["protocol"].get<int>();
        info.version = j["version"]["name"].get<std::string>();
        info.players_max = j["players"]["max"].get<int>();
        info.players_online = j["players"]["online"].get<int>();
        info.description = j["description"]["text"].get<std::string>();
        for (auto t:j["description"]["extra"]) {
            info.description += t["text"].get<std::string>();
        }
        if (!j["favicon"].is_null())
            info.favicon = j["favicon"].get<std::string>();
        info.json = json;
        for (auto t:j["players"]["sample"]) {
            std::pair<std::string, std::string> player;
            player.first = t["id"].get<std::string>();
            player.second = t["name"].get<std::string>();
            info.players.push_back(player);
        }
    } catch (const nlohmann::detail::exception e) {
        std::cerr << "Parsed json is not valid (" << e.id << "): " << e.what() << std::endl;
    }
    //Ping
    Packet packet_ping(0x01);
    Field payload;
    payload.SetLong(771235);
    packet_ping.AddField(payload);
    std::chrono::high_resolution_clock clock;
    auto t1 = clock.now();
    network.SendPacket(packet_ping);
    Packet pong = network.ReceivePacket();
    auto t2 = clock.now();
    pong.ParseField(Long);
    if (pong.GetField(0).GetLong() == 771235) {
        std::chrono::duration<double, std::milli> pingTime = t2 - t1;
        info.ping = pingTime.count();
    }
    return info;
}

NetworkClient::NetworkClient(std::string address, unsigned short port, std::string username) : m_network(address,
                                                                                                         port) {
    m_network.SendHandshake(username);
    Update();
    m_networkThread = std::thread(&NetworkClient::MainLoop, this);
}

NetworkClient::~NetworkClient() {
    isContinue=false;
    m_networkThread.join();
}

Packet * NetworkClient::GetPacket() {
    if (m_received.size() < 1)
        return nullptr;
    Packet packet = m_received.front();
    m_received.pop();
    return new Packet(packet);
}

void NetworkClient::AddPacketToQueue(Packet packet) {
    m_toSend.push(packet);
}

void NetworkClient::Update() {
    if (m_toSend.size() > 0) {
        m_network.SendPacket(m_toSend.front());
        m_toSend.pop();
    }
    Packet received = m_network.ReceivePacket();
    if (received.GetId() == 0x1F) {
        PacketParser::Parse(received);
        Packet response = PacketBuilder::CPlay0x0B(received.GetField(0).GetVarInt());
        m_network.SendPacket(response);
        return;
    }
    m_updateMutex.lock();
    m_received.push(received);
    m_updateMutex.unlock();
}

void NetworkClient::MainLoop() {
    try {
        while (isContinue) {
            Update();
        }
    } catch (int e){
        std::cerr<<"NetworkClient exception: "<<e<<std::endl;
    }

}