Botcraft 26.1.2
Loading...
Searching...
No Matches
ManagersClient.cpp
Go to the documentation of this file.
13
15#if USE_GUI
18#endif
19
20using namespace ProtocolCraft;
21
22namespace Botcraft
23{
25 {
27 is_hardcore = false;
28#if PROTOCOL_VERSION > 463 /* > 1.13.2 */
29 difficulty_locked = true;
30#endif
31
32 world = nullptr;
33 inventory_manager = nullptr;
34 entity_manager = nullptr;
35 physics_manager = nullptr;
36
37#if USE_GUI
38 rendering_manager = nullptr;
39#endif
40 auto_respawn = false;
41
42 // Ensure the assets are loaded
44 }
45
50
52 {
53 std::thread::id network_process_thread_id;
55 {
56 network_process_thread_id = network_manager->GetProcessingThreadId();
57 }
58
60
62#if PROTOCOL_VERSION > 463 /* > 1.13.2 */
63 difficulty_locked = true;
64#endif
65 is_hardcore = false;
66
67 physics_manager.reset();
68 entity_manager.reset();
69 inventory_manager.reset();
70#if USE_GUI
72 {
73 rendering_manager->Close();
74 }
75 rendering_manager.reset();
76#endif
77
78 if (world)
79 {
80 world->UnloadAllChunks(network_process_thread_id);
81 world.reset();
82 }
83
84 {
85 std::scoped_lock<std::shared_mutex> lock(player_names_mutex);
86 player_names.clear();
87 }
88 }
89
91 {
92 return day_time;
93 }
94
95 int ManagersClient::SendInventoryTransaction(const std::shared_ptr<ServerboundContainerClickPacket>& transaction)
96 {
97 InventoryTransaction inventory_transaction = inventory_manager->PrepareTransaction(transaction);
98#if PROTOCOL_VERSION < 755 /* < 1.17 */
99 inventory_manager->AddPendingTransaction(inventory_transaction);
100 network_manager->Send(transaction);
101 return transaction->GetUid();
102#else
103 network_manager->Send(transaction);
104 // In 1.17+ there is no server confirmation so apply it directly
105 inventory_manager->ApplyTransaction(inventory_transaction);
106 return 1;
107#endif
108 }
109
110 void ManagersClient::SetSharedWorld(const std::shared_ptr<World> world_)
111 {
112 world = world_;
113 }
114
116 {
117 return auto_respawn;
118 }
119
121 {
122 auto_respawn = b;
123 }
124
125 std::shared_ptr<World> ManagersClient::GetWorld() const
126 {
127 return world;
128 }
129
130 std::shared_ptr<EntityManager> ManagersClient::GetEntityManager() const
131 {
132 return entity_manager;
133 }
134
135 std::shared_ptr<LocalPlayer> ManagersClient::GetLocalPlayer() const
136 {
137 return entity_manager == nullptr ? nullptr : entity_manager->GetLocalPlayer();
138 }
139
140 std::shared_ptr<InventoryManager> ManagersClient::GetInventoryManager() const
141 {
142 return inventory_manager;
143 }
144
145 std::shared_ptr<PhysicsManager> ManagersClient::GetPhysicsManager() const
146 {
147 return physics_manager;
148 }
149
150 std::string ManagersClient::GetPlayerName(const UUID& uuid) const
151 {
152 std::shared_lock<std::shared_mutex> lock(player_names_mutex);
153 auto it = player_names.find(uuid);
154 if (it != player_names.end())
155 {
156 return it->second;
157 }
158 else if (entity_manager == nullptr || entity_manager->GetLocalPlayer() == nullptr)
159 {
160 return "";
161 }
162 else if (uuid == entity_manager->GetLocalPlayer()->GetUUID())
163 {
164 return network_manager->GetMyName();
165 }
166 return "";
167 }
168
169
170#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
171 void ManagersClient::Handle(ClientboundGameProfilePacket& packet)
172#else
174#endif
175 {
176 // Create all handlers
177 if (!world)
178 {
179 world = std::make_shared<World>(false);
180 }
181
182 inventory_manager = std::make_shared<InventoryManager>();
183 entity_manager = std::make_shared<EntityManager>(network_manager);
184 // Subscribe them to the network manager
185 network_manager->AddHandler(world.get());
186 network_manager->AddHandler(inventory_manager.get());
187 network_manager->AddHandler(entity_manager.get());
188#if USE_GUI
190 {
191 rendering_manager = Renderer::RenderingManager::CreateRenderingManagerIfPossible(world, inventory_manager, entity_manager);
192 if (rendering_manager == nullptr)
193 {
194 static bool first_time = true;
195 if (first_time)
196 {
197 first_time = false;
199 "Having multiple clients with renderer enabled is not supported.\n" <<
200 "Make sure to destroy the rendered client or disable Botcraft::Renderer::Options before creating another one"
201 );
202 }
203 }
204 else
205 {
206 network_manager->AddHandler(rendering_manager.get());
207 }
208 }
209 physics_manager = std::make_shared<PhysicsManager>(rendering_manager, inventory_manager, entity_manager, network_manager, world);
210#else
211 physics_manager = std::make_shared<PhysicsManager>(inventory_manager, entity_manager, network_manager, world);
212#endif
213 network_manager->AddHandler(physics_manager.get());
214 // Start physics
215 physics_manager->StartPhysics();
216 }
217
219 {
220 difficulty = static_cast<Difficulty>(packet.GetDifficulty());
221#if PROTOCOL_VERSION > 463 /* > 1.13.2 */
222 difficulty_locked = packet.GetLocked();
223#endif
224 }
225
227 {
228#if PROTOCOL_VERSION > 768 /* > 1.21.3 */
230#endif
231
232#if PROTOCOL_VERSION > 737 /* > 1.16.1 */
233 is_hardcore = packet.GetHardcore();
234#else
235 is_hardcore = packet.GetGameType() & 0x08;
236#endif
237
238#if PROTOCOL_VERSION < 464 /* < 1.14 */
239 difficulty = static_cast<Difficulty>(packet.GetDifficulty());
240#endif
241 }
242
244 {
245 if (packet.GetHealth() <= 0.0f && auto_respawn)
246 {
247 Respawn();
248 }
249 }
250
252 {
253 // Override the ConnectionClient Handle as the teleport confirmation is sent by the physics manager instead
254 }
255
257 {
258#if PROTOCOL_VERSION > 768 /* > 1.21.3 */
260#endif
261
262#if PROTOCOL_VERSION < 464 /* < 1.14 */
263 difficulty = static_cast<Difficulty>(packet.GetDifficulty());
264#endif
265 }
266
268 {
269 // abs because the server multiplies by -1 to indicate fixed daytime for versions < 1.21.2
270#if PROTOCOL_VERSION < 775 /* 26.1 */
271 day_time = std::abs(packet.GetDayTime()) % 24000;
272#else
273 // Per dimension updates
274 // TODO: match the dimension to ids using registry?
275 if (world != nullptr)
276 {
277 if (world->GetCurrentDimension() == "minecraft:overworld")
278 {
279 auto it = packet.GetClockUpdates().find(0);
280 if (it != packet.GetClockUpdates().end())
281 {
282 day_time = it->second.GetTotalTicks() % 24000;
283 }
284 }
285 else if (world->GetCurrentDimension() == "minecraft:the_end")
286 {
287 auto it = packet.GetClockUpdates().find(1);
288 if (it != packet.GetClockUpdates().end())
289 {
290 day_time = it->second.GetTotalTicks() % 24000;
291 }
292 }
293 }
294#endif
295 }
296
297#if PROTOCOL_VERSION < 761 /* < 1.19.3 */
298 void ManagersClient::Handle(ClientboundPlayerInfoPacket& packet)
299 {
300 if (packet.GetAction() == PlayerInfoAction::RemovePlayer)
301 {
302 std::scoped_lock<std::shared_mutex> lock(player_names_mutex);
303 for (const auto& [uuid, infos] : packet.GetEntries())
304 {
305 player_names.erase(uuid);
306 }
307 }
308 else if (packet.GetAction() == PlayerInfoAction::AddPlayer)
309 {
310 std::scoped_lock<std::shared_mutex> lock(player_names_mutex);
311 for (const auto& [uuid, infos] : packet.GetEntries())
312 {
313 if (infos.GetDisplayName().has_value())
314 {
315 player_names[uuid] = infos.GetDisplayName().value().GetText();
316 }
317 else
318 {
319 player_names[uuid] = infos.GetName();
320 }
321 }
322 }
323 else if (packet.GetAction() == PlayerInfoAction::UpdateDisplayName)
324 {
325 std::scoped_lock<std::shared_mutex> lock(player_names_mutex);
326 for (const auto& [uuid, infos] : packet.GetEntries())
327 {
328 if (infos.GetDisplayName().has_value())
329 {
330 player_names[uuid] = infos.GetDisplayName().value().GetText();
331 }
332 }
333 }
334 }
335#else
337 {
338 std::scoped_lock<std::shared_mutex> lock(player_names_mutex);
339 for (const auto& uuid : packet.GetProfileIds())
340 {
341 player_names.erase(uuid);
342 }
343 }
344
346 {
347 for (const auto& action : packet.GetActions())
348 {
349 if (action == PlayerInfoUpdateAction::AddPlayer)
350 {
351 std::scoped_lock<std::shared_mutex> lock(player_names_mutex);
352 for (const auto& [uuid, infos] : packet.GetEntries())
353 {
354 player_names[uuid] = infos.game_profile.GetName();
355 }
356 continue;
357 }
358 if (action == PlayerInfoUpdateAction::UpdateDisplayName)
359 {
360 std::scoped_lock<std::shared_mutex> lock(player_names_mutex);
361 for (const auto& [uuid, infos] : packet.GetEntries())
362 {
363 if (infos.display_name.has_value())
364 {
365 player_names[uuid] = infos.display_name.value().GetText();
366 }
367 }
368 }
369 }
370 }
371#endif
372} //Botcraft
#define LOG_WARNING(osstream)
Definition Logger.hpp:44
static AssetsManager & getInstance()
void Respawn()
Ask to respawn when dead.
virtual void Handle(ProtocolCraft::ClientboundLoginDisconnectPacket &packet) override
std::shared_ptr< NetworkManager > network_manager
std::atomic< int > day_time
std::map< ProtocolCraft::UUID, std::string > player_names
Names of all connected players.
std::shared_ptr< EntityManager > GetEntityManager() const
std::shared_ptr< PhysicsManager > GetPhysicsManager() const
void SetSharedWorld(const std::shared_ptr< World > world_)
std::shared_ptr< Renderer::RenderingManager > rendering_manager
std::shared_ptr< LocalPlayer > GetLocalPlayer() const
void SetAutoRespawn(const bool b)
std::shared_ptr< InventoryManager > GetInventoryManager() const
virtual void Disconnect() override
std::shared_ptr< PhysicsManager > physics_manager
std::shared_ptr< InventoryManager > inventory_manager
std::shared_ptr< EntityManager > entity_manager
int SendInventoryTransaction(const std::shared_ptr< ProtocolCraft::ServerboundContainerClickPacket > &transaction)
std::shared_mutex player_names_mutex
std::shared_ptr< World > world
virtual void Handle(ProtocolCraft::ClientboundLoginFinishedPacket &packet) override
int GetDayTime() const
Get the current tick.
std::string GetPlayerName(const ProtocolCraft::UUID &uuid) const
Get the name of a connected player.
std::shared_ptr< World > GetWorld() const
static std::shared_ptr< RenderingManager > CreateRenderingManagerIfPossible(std::shared_ptr< World > world_, std::shared_ptr< InventoryManager > inventory_manager_, std::shared_ptr< EntityManager > entity_manager_)
std::array< unsigned char, 16 > UUID