Botcraft 1.21.10
Loading...
Searching...
No Matches
NetworkManager.cpp
Go to the documentation of this file.
1#include <functional>
2#include <optional>
3
8#if USE_COMPRESSION
10#endif
13#if PROTOCOL_VERSION > 758 /* > 1.18.2 */
15#endif
16
17
20
21using namespace ProtocolCraft;
22
23namespace Botcraft
24{
25 NetworkManager::NetworkManager(const std::string& address, const std::string& login_or_microsoft_cache_key_or_mc_token, const AuthType auth_type, const std::vector<Handler*>& handlers)
26 {
27 com = nullptr;
28
29 switch (auth_type)
30 {
32 authentifier = nullptr;
33 name = login_or_microsoft_cache_key_or_mc_token;
34 break;
36 authentifier = std::make_shared<Authentifier>();
37 if (!authentifier->AuthMicrosoft(login_or_microsoft_cache_key_or_mc_token))
38 {
39 throw std::runtime_error("Error trying to authenticate on Mojang server using Microsoft auth flow");
40 }
41 name = authentifier->GetPlayerDisplayName();
42 break;
44 authentifier = std::make_shared<Authentifier>();
45 if (!authentifier->AuthMCToken(login_or_microsoft_cache_key_or_mc_token))
46 {
47 throw std::runtime_error("Error trying to authenticate on Mojang server using provided mc token");
48 }
49 name = authentifier->GetPlayerDisplayName();
50 break;
51 }
52
53 compression = -1;
54 AddHandler(this);
55 for (Handler* p : handlers)
56 {
57 AddHandler(p);
58 }
59
60 state = ConnectionState::Handshake;
61
62 //Start the thread to process the incoming packets
64
65 com = std::make_shared<TCP_Com>(address, std::bind(&NetworkManager::OnNewRawData, this, std::placeholders::_1));
66
67 // Wait for the communication to be ready before sending any data
69 return com->IsInitialized();
70 }, 500, 0);
71
72 std::shared_ptr<ServerboundClientIntentionPacket> handshake_packet = std::make_shared<ServerboundClientIntentionPacket>();
73 handshake_packet->SetProtocolVersion(PROTOCOL_VERSION);
74 handshake_packet->SetHostName(com->GetIp());
75 handshake_packet->SetPort(com->GetPort());
76 handshake_packet->SetIntention(static_cast<int>(ConnectionState::Login));
77 Send(handshake_packet);
78
79 state = ConnectionState::Login;
80
81 std::shared_ptr<ServerboundHelloPacket> loginstart_packet = std::make_shared<ServerboundHelloPacket>();
82#if PROTOCOL_VERSION < 759 /* < 1.19 */
83 loginstart_packet->SetGameProfile(name);
84#else
85 loginstart_packet->SetName_(name);
86 if (authentifier)
87 {
88#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
90 key.SetTimestamp(authentifier->GetKeyTimestamp());
91 key.SetKey(Utilities::RSAToBytes(authentifier->GetPublicKey()));
92 key.SetSignature(Utilities::DecodeBase64(authentifier->GetKeySignature()));
93
94 loginstart_packet->SetPublicKey(key);
95#else
97#endif
98#if PROTOCOL_VERSION > 759 /* > 1.19 */
99 loginstart_packet->SetProfileId(authentifier->GetPlayerUUID());
100#endif
101 }
102#endif
103 Send(loginstart_packet);
104 }
105
106 NetworkManager::NetworkManager(const ConnectionState constant_connection_state)
107 {
108 state = constant_connection_state;
109 compression = -1;
110 }
111
116
118 {
119 state = ConnectionState::None;
120
121 if (com)
122 {
123 com->close();
124 }
125
126 process_condition.notify_all();
127
128 if (m_thread_process.joinable())
129 {
130 m_thread_process.join();
131 }
132 compression = -1;
133
134 com.reset();
135 }
136
138 {
139 subscribed.push_back(h);
140 }
141
142 void NetworkManager::Send(const std::shared_ptr<Packet> packet)
143 {
144 if (com)
145 {
146 std::lock_guard<std::mutex> lock(mutex_send);
147 std::vector<unsigned char> packet_data;
148 packet_data.reserve(256);
149 packet->Write(packet_data);
150 if (compression == -1)
151 {
152 com->SendPacket(packet_data);
153 }
154 else
155 {
156#ifdef USE_COMPRESSION
157 if (packet_data.size() < compression)
158 {
159 packet_data.insert(packet_data.begin(), 0x00);
160 com->SendPacket(packet_data);
161 }
162 else
163 {
164 std::vector<unsigned char> compressed_packet;
165 compressed_packet.reserve(packet_data.size() + 5);
166 WriteData<VarInt>(static_cast<int>(packet_data.size()), compressed_packet);
167 std::vector<unsigned char> compressed_data = Compress(packet_data);
168 compressed_packet.insert(compressed_packet.end(), compressed_data.begin(), compressed_data.end());
169 com->SendPacket(compressed_packet);
170 }
171#else
172 throw std::runtime_error("Program compiled without ZLIB. Cannot send compressed message");
173#endif
174 }
175 }
176 }
177
179 {
180 return state;
181 }
182
183 const std::string& NetworkManager::GetMyName() const
184 {
185 return name;
186 }
187
188 void NetworkManager::SendChatMessage(const std::string& message)
189 {
190#if PROTOCOL_VERSION > 758 /* > 1.18.2 */
191 if (message[0] == '/')
192 {
193 LOG_INFO("You're trying to send a message starting with '/'. Use SendChatCommand instead if you want the server to interprete it as a command.");
194 }
195#endif
196
197 std::shared_ptr<ServerboundChatPacket> chat_message = std::make_shared<ServerboundChatPacket>();
198 chat_message->SetMessage(message);
199#if PROTOCOL_VERSION > 758 /* > 1.18.2 */
200#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
201 chat_message->SetSignedPreview(false);
202#endif
203 if (authentifier)
204 {
205 long long int salt, timestamp;
206 std::vector<unsigned char> signature;
207#if PROTOCOL_VERSION == 759 /* 1.19 */
208 // 1.19
209 signature = authentifier->GetMessageSignature(message, salt, timestamp);
210#elif PROTOCOL_VERSION == 760 /* 1.19.1/2 */
211 // 1.19.1 and 1.19.2
212 LastSeenMessagesUpdate last_seen_update;
213 {
214 std::scoped_lock<std::mutex> lock_messages(chat_context.GetMutex());
215 last_seen_update = chat_context.GetLastSeenMessagesUpdate();
216 signature = authentifier->GetMessageSignature(message, chat_context.GetLastSignature(), last_seen_update.GetLastSeen(), salt, timestamp);
217 // Update last signature with current one for the next message
218 chat_context.SetLastSignature(signature);
219 }
220 chat_message->SetLastSeenMessages(last_seen_update);
221#else
222 // 1.19.3+
223 const auto [signatures, updates] = chat_context.GetLastSeenMessagesUpdate();
224 const int current_message_sent_index = message_sent_index++;
225 signature = authentifier->GetMessageSignature(message, current_message_sent_index, chat_session_uuid, signatures, salt, timestamp);
226 chat_message->SetLastSeenMessages(updates);
227#endif
228 if (signature.empty())
229 {
230 throw std::runtime_error("Empty chat message signature.");
231 }
232 chat_message->SetTimestamp(timestamp);
233
234#if PROTOCOL_VERSION < 760 /* < 1.19.1 */
235 SaltSignature salt_signature;
236 salt_signature.SetSalt(salt);
237 salt_signature.SetSignature(signature);
238
239 chat_message->SetSaltSignature(salt_signature);
240#else
241 chat_message->SetSalt(salt);
242 chat_message->SetSignature(signature);
243#endif
244 }
245 // Offline mode, empty signature
246 else
247 {
248 chat_message->SetTimestamp(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
249 }
250#endif
251 Send(chat_message);
252 }
253
254 void NetworkManager::SendChatCommand(const std::string& command)
255 {
256#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
257 if (authentifier == nullptr)
258 {
259 std::shared_ptr<ServerboundChatCommandPacket> chat_command = std::make_shared<ServerboundChatCommandPacket>();
260 chat_command->SetCommand(command);
261 Send(chat_command);
262 return;
263 }
264#endif
265#if PROTOCOL_VERSION > 758 /* > 1.18.2 */
266#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
267 std::shared_ptr<ServerboundChatCommandSignedPacket> chat_command = std::make_shared<ServerboundChatCommandSignedPacket>();
268#else
269 std::shared_ptr<ServerboundChatCommandPacket> chat_command = std::make_shared<ServerboundChatCommandPacket>();
270#endif
271 chat_command->SetCommand(command);
272 chat_command->SetTimestamp(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
273#if PROTOCOL_VERSION > 759 /* > 1.19 */
274 std::mt19937 rnd(static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count()));
275 chat_command->SetSalt(std::uniform_int_distribution<long long int>(std::numeric_limits<long long int>::min(), std::numeric_limits<long long int>::max())(rnd));
276#endif
277#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
278 chat_command->SetSignedPreview(false);
279#endif
280#if PROTOCOL_VERSION == 760 /* 1.19.1/2 */
281 LastSeenMessagesUpdate last_seen_update;
282 if (authentifier)
283 {
284 std::scoped_lock<std::mutex> lock_messages(chat_context.GetMutex());
285 last_seen_update = chat_context.GetLastSeenMessagesUpdate();
286 }
287 chat_command->SetLastSeenMessages(last_seen_update);
288#elif PROTOCOL_VERSION > 760 /* > 1.19.2 */
289 const auto [signatures, updates] = chat_context.GetLastSeenMessagesUpdate();
290 chat_command->SetLastSeenMessages(updates);
291#endif
292 // TODO: when this shouldn't be empty? Can't find a situation where it's filled with something
293 chat_command->SetArgumentSignatures({});
294#else
295 std::shared_ptr<ServerboundChatPacket> chat_command = std::make_shared<ServerboundChatPacket>();
296 chat_command->SetMessage("/" + command);
297#endif
298 Send(chat_command);
299 }
300
302 {
303 return m_thread_process.get_id();
304 }
305
307 {
308 Logger::GetInstance().RegisterThread("NetworkPacketProcessing - " + name);
309 try
310 {
311 while (state != ConnectionState::None)
312 {
313 {
314 std::unique_lock<std::mutex> lck(mutex_process);
315 process_condition.wait(lck);
316 }
317 while (!packets_to_process.empty())
318 {
319 std::vector<unsigned char> packet;
320 { // process_guard scope
321 std::lock_guard<std::mutex> process_guard(mutex_process);
322 if (!packets_to_process.empty())
323 {
324 packet = packets_to_process.front();
325 packets_to_process.pop();
326 }
327 }
328 if (packet.size() > 0)
329 {
330 if (compression == -1)
331 {
332 ProcessPacket(packet);
333 }
334 else
335 {
336#ifdef USE_COMPRESSION
337 size_t length = packet.size();
338 ReadIterator iter = packet.begin();
339 int data_length = ReadData<VarInt>(iter, length);
340
341 //Packet not compressed
342 if (data_length == 0)
343 {
344 //Erase the first 0
345 packet.erase(packet.begin());
346 ProcessPacket(packet);
347 }
348 //Packet compressed
349 else
350 {
351 const int size_varint = static_cast<int>(packet.size() - length);
352
353 std::vector<unsigned char> uncompressed_packet = Decompress(packet, size_varint);
354 ProcessPacket(uncompressed_packet);
355 }
356#else
357 throw std::runtime_error("Program compiled without USE_COMPRESSION. Cannot read compressed message");
358#endif
359 }
360 }
361 }
362 }
363 }
364 catch (const std::exception& e)
365 {
366 LOG_FATAL("Exception:\n" << e.what());
367 throw;
368 }
369 catch (...)
370 {
371 LOG_FATAL("Unknown exception");
372 throw;
373 }
374 }
375
376 void NetworkManager::ProcessPacket(const std::vector<unsigned char>& bytes)
377 {
378 if (bytes.empty())
379 {
380 return;
381 }
382
383 std::vector<unsigned char>::const_iterator packet_iterator = bytes.begin();
384 size_t length = bytes.size();
385
386 const int packet_id = ReadData<VarInt>(packet_iterator, length);
387
388 std::shared_ptr<Packet> packet = CreateClientboundPacket(state, packet_id);
389
390 if (packet != nullptr)
391 {
392 try
393 {
394 packet->Read(packet_iterator, length);
395 }
396 catch (const std::exception& e)
397 {
398 LOG_FATAL("Parsing exception while parsing message \"" << packet->GetName() << "\"\n" << e.what());
399 throw;
400 }
401 for (size_t i = 0; i < subscribed.size(); i++)
402 {
403 packet->Dispatch(subscribed[i]);
404 }
405 }
406 }
407
408 void NetworkManager::OnNewRawData(const std::vector<unsigned char>& bytes)
409 {
410 {
411 std::unique_lock<std::mutex> lck(mutex_process);
412 packets_to_process.push(bytes);
413 }
414 process_condition.notify_all();
415 }
416
417
419 {
420 compression = packet.GetCompressionThreshold();
421 }
422
423#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
424 void NetworkManager::Handle(ClientboundGameProfilePacket& packet)
425#else
427#endif
428 {
429#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
430 state = ConnectionState::Play;
431#else
432 state = ConnectionState::Configuration;
433 std::shared_ptr<ServerboundLoginAcknowledgedPacket> login_ack_packet = std::make_shared<ServerboundLoginAcknowledgedPacket>();
434 Send(login_ack_packet);
435#endif
436 }
437
439 {
440 if (authentifier == nullptr
441#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
442 && packet.GetShouldAuthenticate()
443#endif
444 )
445 {
446 throw std::runtime_error("Authentication asked while no valid account has been provided, make sure to connect with a valid Microsoft Account, or to a server with online-mode=false");
447 }
448
449#ifdef USE_ENCRYPTION
450 std::shared_ptr<AESEncrypter> encrypter = std::make_shared<AESEncrypter>();
451
452 std::vector<unsigned char> raw_shared_secret;
453 std::vector<unsigned char> encrypted_shared_secret;
454
455#if PROTOCOL_VERSION < 759 /* < 1.19 */
456 std::vector<unsigned char> encrypted_nonce;
457 encrypter->Init(packet.GetPublicKey(), packet.GetNonce(),
458 raw_shared_secret, encrypted_nonce, encrypted_shared_secret);
459#elif PROTOCOL_VERSION < 761 /* < 1.19.3 */
460 std::vector<unsigned char> salted_nonce_signature;
461 long long int salt;
462 encrypter->Init(packet.GetPublicKey(), packet.GetNonce(), authentifier->GetPrivateKey(),
463 raw_shared_secret, encrypted_shared_secret,
464 salt, salted_nonce_signature);
465#else
466 std::vector<unsigned char> encrypted_challenge;
467 encrypter->Init(packet.GetPublicKey(), packet.GetChallenge(),
468 raw_shared_secret, encrypted_shared_secret,
469 encrypted_challenge);
470#endif
471
472 // In 1.20.5+, encryption can be enabled even in offline mode
473#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
474 if (packet.GetShouldAuthenticate())
475#endif
476 {
477 authentifier->JoinServer(packet.GetServerId(), raw_shared_secret, packet.GetPublicKey());
478 }
479
480 std::shared_ptr<ServerboundKeyPacket> response_packet = std::make_shared<ServerboundKeyPacket>();
481 response_packet->SetKeyBytes(encrypted_shared_secret);
482
483#if PROTOCOL_VERSION < 759 /* < 1.19 */
484 // Pre-1.19 behaviour, send encrypted nonce
485 response_packet->SetNonce(encrypted_nonce);
486#elif PROTOCOL_VERSION < 761 /* < 1.19.3 */
487 // 1.19, 1.19.1, 1.19.2 behaviour, send salted nonce signature
488 SaltSignature salt_signature;
489 salt_signature.SetSalt(salt);
490 salt_signature.SetSignature(salted_nonce_signature);
491 response_packet->SetSaltSignature(salt_signature);
492#else
493 // 1.19.3+ behaviour, send encrypted challenge
494 response_packet->SetEncryptedChallenge(encrypted_challenge);
495#endif
496
497 Send(response_packet);
498
499 // Enable encryption from now on
500 com->SetEncrypter(encrypter);
501#else
502 throw std::runtime_error("Your version of botcraft doesn't support encryption. Either run your server with online-mode=false or recompile botcraft");
503#endif
504 }
505
507 {
508 std::shared_ptr<ServerboundKeepAlivePacket> keep_alive_packet = std::make_shared<ServerboundKeepAlivePacket>();
509 keep_alive_packet->SetId_(packet.GetId_());
510 Send(keep_alive_packet);
511 }
512
513#if PROTOCOL_VERSION > 754 /* > 1.16.5 */
515 {
516 std::shared_ptr<ServerboundPongPacket> pong_packet = std::make_shared<ServerboundPongPacket>();
517 pong_packet->SetId_(packet.GetId_());
518 Send(pong_packet);
519 }
520#endif
521
522#if PROTOCOL_VERSION > 340 /* > 1.12.2 */
524 {
525 // Vanilla like response when asked by fabric API
526 // Not implemented in fabric before December 05 2020,
527 // so not necessary before version 1.16.4
528#if PROTOCOL_VERSION > 753 /* > 1.16.3 */
529 if (packet.GetIdentifier().GetFull() == "fabric-networking-api-v1:early_registration")
530 {
531#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
532 std::shared_ptr<ServerboundCustomQueryPacket> custom_query_anwser = std::make_shared<ServerboundCustomQueryPacket>();
533 custom_query_anwser->SetTransactionId(packet.GetTransactionId());
534 custom_query_anwser->SetData(std::nullopt);
535#else
536 std::shared_ptr<ServerboundCustomQueryAnswerPacket> custom_query_anwser = std::make_shared<ServerboundCustomQueryAnswerPacket>();
537 custom_query_anwser->SetTransactionId(packet.GetTransactionId());
538 custom_query_anwser->SetPayload(std::nullopt);
539#endif
540 Send(custom_query_anwser);
541 return;
542 }
543#endif
544 }
545#endif
546
547#if PROTOCOL_VERSION > 759 /* > 1.19 */
549 {
550#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
551 // Ugly stuff because there is a GetMessage macro in Windows API somewhere :)
552#if _MSC_VER || __MINGW32__
553#pragma push_macro("GetMessage")
554#undef GetMessage
555#endif
556 chat_context.AddSeenMessage(packet.GetMessage().GetHeaderSignature(), packet.GetMessage().GetSignedHeader().GetSender());
557#if _MSC_VER || __MINGW32__
558#pragma pop_macro("GetMessage")
559#endif
560#else
561 if (packet.GetSignature().has_value())
562 {
563 std::scoped_lock<std::mutex> lock_messages(chat_context.GetMutex());
564
565 chat_context.AddSeenMessage(std::vector<unsigned char>(packet.GetSignature().value().begin(), packet.GetSignature().value().end()));
566
567 if (chat_context.GetOffset() > 64)
568 {
569 std::shared_ptr<ServerboundChatAckPacket> ack_packet = std::make_shared<ServerboundChatAckPacket>();
570 ack_packet->SetOffset(chat_context.GetAndResetOffset());
571 Send(ack_packet);
572 }
573 }
574#endif
575 }
576
577#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
578 void NetworkManager::Handle(ClientboundPlayerChatHeaderPacket& packet)
579 {
580 chat_context.AddSeenMessage(packet.GetHeaderSignature(), packet.GetHeader().GetSender());
581 }
582#endif
583#endif
584
585#if PROTOCOL_VERSION > 760 /* > 1.19.2 */
587 {
588 if (authentifier)
589 {
590 std::shared_ptr<ServerboundChatSessionUpdatePacket> chat_session_packet = std::make_shared<ServerboundChatSessionUpdatePacket>();
591 RemoteChatSessionData chat_session_data;
592
594 key.SetTimestamp(authentifier->GetKeyTimestamp());
595 key.SetKey(Utilities::RSAToBytes(authentifier->GetPublicKey()));
596 key.SetSignature(Utilities::DecodeBase64(authentifier->GetKeySignature()));
597
598 chat_session_data.SetProfilePublicKey(key);
600 std::mt19937 rnd = std::mt19937(static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count()));
601 std::uniform_int_distribution<int> distrib(std::numeric_limits<unsigned char>::min(), std::numeric_limits<unsigned char>::max());
602 for (size_t i = 0; i < chat_session_uuid.size(); ++i)
603 {
604 chat_session_uuid[i] = static_cast<unsigned char>(distrib(rnd));
605 }
606 chat_session_data.SetUuid(chat_session_uuid);
607
608 chat_session_packet->SetChatSession(chat_session_data);
609 Send(chat_session_packet);
610 }
611 }
612#endif
613
614#if PROTOCOL_VERSION > 763 /* > 1.20.1 */
616 {
617 state = ConnectionState::Play;
618 std::shared_ptr<ServerboundFinishConfigurationPacket> finish_config_packet = std::make_shared<ServerboundFinishConfigurationPacket>();
619 Send(finish_config_packet);
620 }
621
623 {
624 std::shared_ptr<ServerboundKeepAliveConfigurationPacket> keep_alive_packet = std::make_shared<ServerboundKeepAliveConfigurationPacket>();
625 keep_alive_packet->SetId_(packet.GetId_());
626 Send(keep_alive_packet);
627 }
628
630 {
631 std::shared_ptr<ServerboundPongConfigurationPacket> pong_packet = std::make_shared<ServerboundPongConfigurationPacket>();
632 pong_packet->SetId_(packet.GetId_());
633 Send(pong_packet);
634 }
635
637 {
638 state = ConnectionState::Configuration;
639 std::shared_ptr<ServerboundConfigurationAcknowledgedPacket> config_ack_packet = std::make_shared<ServerboundConfigurationAcknowledgedPacket>();
640 Send(config_ack_packet);
641 }
642
644 {
645 chunk_batch_start_time = std::chrono::steady_clock::now();
646 }
647
649 {
650 using count_return = decltype(std::declval<std::chrono::milliseconds>().count());
651 const count_return time_elapsed_ms = std::max(static_cast<count_return>(1), std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - chunk_batch_start_time).count());
652 std::shared_ptr<ServerboundChunkBatchReceivedPacket> chunk_per_tick_packet = std::make_shared<ServerboundChunkBatchReceivedPacket>();
653 // Ask as many chunks as we can process in one tick (50 ms)
654 chunk_per_tick_packet->SetDesiredChunksPerTick(packet.GetBatchSize() * 50.0f / time_elapsed_ms);
655 Send(chunk_per_tick_packet);
656 }
657#endif
658
659#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
661 {
662 std::shared_ptr<ServerboundSelectKnownPacksPacket> select_known_packs = std::make_shared<ServerboundSelectKnownPacksPacket>();
663 // Datapacks are not supported by Botcraft
664 select_known_packs->SetKnownPacks({});
665
666 Send(select_known_packs);
667
668 }
669#endif
670}
#define LOG_INFO(osstream)
Definition Logger.hpp:43
#define LOG_FATAL(osstream)
Definition Logger.hpp:46
void AddSeenMessage(const std::vector< unsigned char > &signature)
std::pair< std::vector< std::vector< unsigned char > >, ProtocolCraft::LastSeenMessagesUpdate > GetLastSeenMessagesUpdate()
Get both a vector of previous messages signatures and the LastSeenMessagesUpdate object.
void RegisterThread(const std::string &name)
Register the current thread in the map.
Definition Logger.cpp:104
static Logger & GetInstance()
Definition Logger.cpp:36
std::condition_variable process_condition
void AddHandler(ProtocolCraft::Handler *h)
virtual void Handle(ProtocolCraft::ClientboundLoginCompressionPacket &packet) override
std::thread::id GetProcessingThreadId() const
void SendChatCommand(const std::string &command)
void Send(const std::shared_ptr< ProtocolCraft::Packet > packet)
void SendChatMessage(const std::string &message)
void ProcessPacket(const std::vector< unsigned char > &bytes)
LastSeenMessagesTracker chat_context
std::shared_ptr< TCP_Com > com
void OnNewRawData(const std::vector< unsigned char > &bytes)
std::chrono::steady_clock::time_point chunk_batch_start_time
const std::string & GetMyName() const
std::shared_ptr< Authentifier > authentifier
const ProtocolCraft::ConnectionState GetConnectionState() const
std::vector< ProtocolCraft::Handler * > subscribed
std::atomic< int > message_sent_index
ProtocolCraft::ConnectionState state
std::queue< std::vector< unsigned char > > packets_to_process
ProtocolCraft::UUID chat_session_uuid
NetworkManager(const std::string &address, const std::string &login_or_microsoft_cache_key_or_mc_token, const AuthType auth_type, const std::vector< ProtocolCraft::Handler * > &handlers={})
std::vector< unsigned char > RSAToBytes(const std::string &s)
std::vector< unsigned char > DecodeBase64(const std::string &s)
bool WaitForCondition(const std::function< bool()> &condition, const long long int timeout_ms=0, const long long int check_interval_ms=10)
std::vector< unsigned char > Decompress(const std::vector< unsigned char > &compressed, const int start=0)
std::vector< unsigned char > Compress(const std::vector< unsigned char > &raw)
std::shared_ptr< Packet > CreateClientboundPacket(const ConnectionState state, const int id)
std::array< unsigned char, 16 > UUID
std::vector< unsigned char >::const_iterator ReadIterator