Botcraft 1.21.10
Loading...
Searching...
No Matches
EntityManager.cpp
Go to the documentation of this file.
6
8
9namespace Botcraft
10{
11 EntityManager::EntityManager(const std::shared_ptr<NetworkManager>& network_manager) : network_manager(network_manager)
12 {
13 local_player = nullptr;
14 }
15
16 std::shared_ptr<LocalPlayer> EntityManager::GetLocalPlayer()
17 {
18 return local_player;
19 }
20
21 std::shared_ptr<Entity> EntityManager::GetEntity(const int id) const
22 {
23 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
24 auto it = entities.find(id);
25 return it == entities.end() ? nullptr : it->second;
26 }
27
28 void EntityManager::AddEntity(const std::shared_ptr<Entity>& entity)
29 {
30 if (entity == nullptr)
31 {
32 return;
33 }
34
35 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
36 entities[entity->GetEntityID()] = entity;
37 }
38
43
44
46 {
47 local_player = std::make_shared<LocalPlayer>();
48 local_player->SetEntityID(packet.GetPlayerId());
49#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
50 local_player->SetGameMode(static_cast<GameType>(packet.GetGameType() & 0x03));
51#else
52 local_player->SetGameMode(static_cast<GameType>(packet.GetCommonPlayerSpawnInfo().GetGameType()));
53#endif
54 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
55 entities[packet.GetPlayerId()] = local_player;
56 }
57
58#if PROTOCOL_VERSION < 755 /* < 1.17 */
59 void EntityManager::Handle(ProtocolCraft::ClientboundMoveEntityPacket& packet)
60 {
61 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
62 auto it = entities.find(packet.GetEntityId());
63 if (it == entities.end())
64 {
65 std::shared_ptr<Entity> entity = std::make_shared<UnknownEntity>();
66 entity->SetEntityID(packet.GetEntityId());
67 entities[packet.GetEntityId()] = entity;
68 }
69 }
70#endif
71
73 {
74 std::shared_ptr<Entity> entity = nullptr;
75
76 {
77 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
78 auto it = entities.find(packet.GetEntityId());
79 if (it != entities.end())
80 {
81 entity = it->second;
82 }
83 }
84
85 if (entity != nullptr)
86 {
87 const Vector3<double> entity_position = entity->GetPosition();
88 entity->SetPosition(Vector3<double>(
89 (packet.GetXA() / 128.0f + entity_position.x * 32.0f) / 32.0f,
90 (packet.GetYA() / 128.0f + entity_position.y * 32.0f) / 32.0f,
91 (packet.GetZA() / 128.0f + entity_position.z * 32.0f) / 32.0f
92 ));
93 entity->SetOnGround(packet.GetOnGround());
94 }
95 }
96
98 {
99 std::shared_ptr<Entity> entity = nullptr;
100
101 {
102 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
103 auto it = entities.find(packet.GetEntityId());
104 if (it != entities.end())
105 {
106 entity = it->second;
107 }
108 }
109
110 if (entity != nullptr)
111 {
112 const Vector3<double> entity_position = entity->GetPosition();
113 entity->SetPosition(Vector3<double>(
114 (packet.GetXA() / 128.0f + entity_position.x * 32.0f) / 32.0f,
115 (packet.GetYA() / 128.0f + entity_position.y * 32.0f) / 32.0f,
116 (packet.GetZA() / 128.0f + entity_position.z * 32.0f) / 32.0f
117 ));
118 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
119 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
120 entity->SetOnGround(packet.GetOnGround());
121 }
122 }
123
125 {
126 std::shared_ptr<Entity> entity = nullptr;
127
128 {
129 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
130 auto it = entities.find(packet.GetEntityId());
131 if (it != entities.end())
132 {
133 entity = it->second;
134 }
135 }
136
137 if (entity != nullptr)
138 {
139 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
140 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
141 entity->SetOnGround(packet.GetOnGround());
142 }
143 }
144
146 {
147#if PROTOCOL_VERSION < 458 /* < 1.14 */
148 std::shared_ptr<Entity> entity = Entity::CreateObjectEntity(static_cast<ObjectEntityType>(packet.GetType()));
149#else
150 std::shared_ptr<Entity> entity = Entity::CreateEntity(static_cast<EntityType>(packet.GetType()));
151#endif
152
153 entity->SetEntityID(packet.GetEntityId());
154 entity->SetX(packet.GetX());
155 entity->SetY(packet.GetY());
156 entity->SetZ(packet.GetZ());
157 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
158 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
159 entity->SetUUID(packet.GetUuid());
160#if PROTOCOL_VERSION < 773 /* < 1.21.9 */
161 // Packet data is in 1/8000 of block per tick, so convert it back to block/tick
162 entity->SetSpeed(Vector3<double>(packet.GetXa(), packet.GetYa(), packet.GetZa()) / 8000.0);
163#else
164 entity->SetSpeed(Vector3<double>(packet.GetMovement()));
165#endif
166
167 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
168 entities[packet.GetEntityId()] = entity;
169 }
170
171#if PROTOCOL_VERSION < 759 /* < 1.19 */
172 void EntityManager::Handle(ProtocolCraft::ClientboundAddMobPacket& packet)
173 {
174 std::shared_ptr<Entity> entity = Entity::CreateEntity(static_cast<EntityType>(packet.GetType()));
175
176 entity->SetEntityID(packet.GetEntityId());
177 entity->SetX(packet.GetX());
178 entity->SetY(packet.GetY());
179 entity->SetZ(packet.GetZ());
180 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
181 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
182 entity->SetUUID(packet.GetUuid());
183
184 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
185 entities[packet.GetEntityId()] = entity;
186 }
187#endif
188
189#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
190 void EntityManager::Handle(ProtocolCraft::ClientboundAddExperienceOrbPacket& packet)
191 {
192 std::shared_ptr<Entity> entity = Entity::CreateEntity(EntityType::ExperienceOrb);
193
194 entity->SetEntityID(packet.GetEntityId());
195 entity->SetX(packet.GetX());
196 entity->SetY(packet.GetY());
197 entity->SetZ(packet.GetZ());
198 // What do we do with the xp value?
199 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
200 entities[packet.GetEntityId()] = entity;
201 }
202#endif
203
204#if PROTOCOL_VERSION < 721 /* < 1.16 */
205 void EntityManager::Handle(ProtocolCraft::ClientboundAddGlobalEntityPacket& packet)
206 {
207 std::shared_ptr<Entity> entity = Entity::CreateEntity(static_cast<EntityType>(packet.GetType()));
208
209 entity->SetEntityID(packet.GetEntityId());
210 entity->SetX(packet.GetX());
211 entity->SetY(packet.GetY());
212 entity->SetZ(packet.GetZ());
213
214 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
215 entities[packet.GetEntityId()] = entity;
216 }
217#endif
218
219#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
220 void EntityManager::Handle(ProtocolCraft::ClientboundAddPlayerPacket& packet)
221 {
222 std::shared_ptr<Entity> entity = nullptr;
223
224 {
225 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
226 auto it = entities.find(packet.GetEntityId());
227 if (it == entities.end())
228 {
230 entities[packet.GetEntityId()] = entity;
231 }
232 else
233 {
234 entity = it->second;
235 }
236 }
237
238 entity->SetEntityID(packet.GetEntityId());
239 entity->SetPosition(Vector3<double>(
240 packet.GetX(),
241 packet.GetY(),
242 packet.GetZ()
243 ));
244 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
245 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
246 entity->SetUUID(packet.GetPlayerId());
247 }
248#endif
249
251 {
252 local_player->SetHealth(packet.GetHealth());
253 local_player->SetFood(packet.GetFood());
254 local_player->SetFoodSaturation(packet.GetFoodSaturation());
255 }
256
258 {
259 std::shared_ptr<Entity> entity = nullptr;
260
261 {
262 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
263 auto it = entities.find(packet.GetEntityId());
264 if (it != entities.end())
265 {
266 entity = it->second;
267 }
268 }
269
270 if (entity != nullptr)
271 {
272#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
273 entity->SetPosition(Vector3<double>(
274 packet.GetX(),
275 packet.GetY(),
276 packet.GetZ()
277 ));
278 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
279 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
280#else
281 entity->SetPosition(Vector3<double>(
282 packet.GetRelatives() & (1 << 0) ? entity->GetX() + packet.GetChange().GetPosition()[0] : packet.GetChange().GetPosition()[0],
283 packet.GetRelatives() & (1 << 1) ? entity->GetY() + packet.GetChange().GetPosition()[1] : packet.GetChange().GetPosition()[1],
284 packet.GetRelatives() & (1 << 2) ? entity->GetZ() + packet.GetChange().GetPosition()[2] : packet.GetChange().GetPosition()[2]
285 ));
286 entity->SetYaw(packet.GetRelatives() & (1 << 3) ? entity->GetYaw() + packet.GetChange().GetYRot() : packet.GetChange().GetYRot());
287 entity->SetPitch(packet.GetRelatives() & (1 << 4) ? entity->GetPitch() + packet.GetChange().GetXRot() : packet.GetChange().GetXRot());
288#endif
289 entity->SetOnGround(packet.GetOnGround());
290 }
291 }
292
294 {
295 local_player->SetAbilitiesFlags(packet.GetFlags());
296 local_player->SetFlyingSpeed(packet.GetFlyingSpeed());
297 local_player->SetWalkingSpeed(packet.GetWalkingSpeed());
298 }
299
300#if PROTOCOL_VERSION == 755 /* 1.17 */
301 void EntityManager::Handle(ProtocolCraft::ClientboundRemoveEntityPacket& packet)
302 {
303 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
304 entities.erase(packet.GetEntityId());
305 }
306#else
308 {
309 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
310 for (int i = 0; i < packet.GetEntityIds().size(); ++i)
311 {
312 entities.erase(packet.GetEntityIds()[i]);
313 }
314 }
315#endif
316
318 {
319#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
320 local_player->SetGameMode(static_cast<GameType>(packet.GetPlayerGameType()));
321#else
322 local_player->SetGameMode(static_cast<GameType>(packet.GetCommonPlayerSpawnInfo().GetGameType()));
323#endif
324 }
325
327 {
328 switch (packet.GetType())
329 {
330 case 3: // CHANGE_GAME_MODE
331 local_player->SetGameMode(static_cast<GameType>(packet.GetParam()));
332 break;
333 default:
334 break;
335 }
336 }
337
339 {
340 std::shared_ptr<Entity> entity = nullptr;
341
342 {
343 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
344 auto it = entities.find(packet.GetEntityId());
345 if (it != entities.end())
346 {
347 entity = it->second;
348 }
349 }
350
351 if (entity == nullptr)
352 {
353 LOG_WARNING("Trying to load metadata in unexisting entity");
354 }
355 else
356 {
357 entity->LoadMetadataFromRawArray(packet.GetPackedItems());
358 }
359 }
360
362 {
363 std::shared_ptr<Entity> entity = nullptr;
364
365 {
366 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
367 auto it = entities.find(packet.GetEntityId());
368 if (it != entities.end())
369 {
370 entity = it->second;
371 }
372 }
373
374 if (entity == nullptr)
375 {
376 LOG_WARNING("Trying to set speed of an unexisting entity");
377 }
378 else
379 {
380#if PROTOCOL_VERSION < 773 /* < 1.21.9 */
381 // Packet data is in 1/8000 of block per tick, so convert it back to block/tick
382 entity->SetSpeed(Vector3<double>(packet.GetXA(), packet.GetYA(), packet.GetZA()) / 8000.0);
383#else
384 entity->SetSpeed(Vector3<double>(packet.GetMovement()));
385#endif
386 }
387 }
388
390 {
391 std::shared_ptr<Entity> entity = nullptr;
392
393 {
394 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
395 auto it = entities.find(packet.GetEntityId());
396 if (it != entities.end())
397 {
398 entity = it->second;
399 }
400 }
401
402 if (entity == nullptr)
403 {
404 LOG_WARNING("Trying to set equipment of an unexisting entity");
405 }
406 else
407 {
408#if PROTOCOL_VERSION > 730 /* > 1.15.2 */
409 for (auto& p : packet.GetSlots())
410 {
411 entity->SetEquipment(static_cast<EquipmentSlot>(p.first), p.second);
412 }
413#else
414 entity->SetEquipment(static_cast<EquipmentSlot>(packet.GetSlot().first), packet.GetSlot().second);
415#endif
416 }
417 }
418
420 {
421 std::shared_ptr<Entity> entity = nullptr;
422
423 {
424 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
425 auto it = entities.find(packet.GetEntityId());
426 if (it != entities.end())
427 {
428 entity = it->second;
429 }
430 }
431
432 if (entity == nullptr)
433 {
434 LOG_WARNING("Trying to set attributes of an unexisting entity");
435 }
436 else if (!entity->IsLivingEntity())
437 {
438 LOG_WARNING("Trying to set attributes of a non LivingEntity");
439 }
440 else
441 {
442 std::shared_ptr<LivingEntity> living_entity = std::dynamic_pointer_cast<LivingEntity>(entity);
443 for (const auto& a : packet.GetAttributes())
444 {
445#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
446 const EntityAttribute::Type type = static_cast<EntityAttribute::Type>(a.GetKey());
447#elif PROTOCOL_VERSION > 709 /* > 1.15.2 */
448 const EntityAttribute::Type type = EntityAttribute::StringToType(a.GetKey().GetFull());
449#else
450 const EntityAttribute::Type type = EntityAttribute::StringToType(a.GetKey());
451#endif
452 EntityAttribute attribute(type, a.GetValue());
453 for (const auto& m : a.GetModifiers())
454 {
455 attribute.SetModifier(
456#if PROTOCOL_VERSION < 767 /* < 1.21 */
457 m.GetUuid(),
458#else
459 m.GetId().GetFull(),
460#endif
461 EntityAttribute::Modifier{ m.GetAmount(), static_cast<EntityAttribute::Modifier::Operation>(m.GetOperation()) }
462 );
463 }
464 living_entity->AddAttribute(attribute);
465 }
466 }
467 }
468
470 {
471 std::shared_ptr<Entity> entity = nullptr;
472
473 {
474 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
475 auto it = entities.find(packet.GetEntityId());
476 if (it != entities.end())
477 {
478 entity = it->second;
479 }
480 }
481
482 if (entity == nullptr)
483 {
484 LOG_WARNING("Trying to set effect of an unexisting entity");
485 }
486 else
487 {
488 entity->AddEffect(EntityEffect {
489 static_cast<EntityEffectType>(packet.GetEffectId()), // type
490 static_cast<unsigned char>(packet.GetEffectAmplifier()), //amplifier
491 std::chrono::steady_clock::now() + std::chrono::milliseconds(50 * packet.GetEffectDurationTicks()) // end
492 });
493 }
494 }
495
497 {
498
499 std::shared_ptr<Entity> entity = nullptr;
500
501 {
502 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
503 auto it = entities.find(packet.GetEntityId());
504 if (it != entities.end())
505 {
506 entity = it->second;
507 }
508 }
509
510 if (entity == nullptr)
511 {
512 LOG_WARNING("Trying to remove effect of an unexisting entity");
513 }
514 else
515 {
516 entity->RemoveEffect(static_cast<EntityEffectType>(packet.GetEffect()));
517 }
518 }
519
520#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
522 {
523 std::shared_ptr<Entity> entity = nullptr;
524
525 {
526 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
527 auto it = entities.find(packet.GetEntityId());
528 if (it != entities.end())
529 {
530 entity = it->second;
531 }
532 }
533
534 if (entity != nullptr)
535 {
536 entity->SetPosition(packet.GetValues().GetPosition());
537 if (entity == local_player)
538 {
539 return;
540 }
541 entity->SetYaw(packet.GetValues().GetYRot());
542 entity->SetPitch(packet.GetValues().GetXRot());
543 entity->SetOnGround(packet.GetOnGround());
544 }
545 }
546
548 {
549 std::shared_ptr<Entity> entity = nullptr;
550
551 {
552 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
553 auto it = entities.find(packet.GetEntityId());
554 if (it != entities.end())
555 {
556 entity = it->second;
557 }
558 }
559
560 if (entity == nullptr || !entity->IsAbstractMinecart())
561 {
562 return;
563 }
564
565 // Don't lerp, directly set the position to the last lerp step
566
567 const ProtocolCraft::MinecartBehaviorMinecartStep& step = packet.GetLerpSteps().back();
568 entity->SetPosition(step.GetPosition());
569 entity->SetYaw(360.0f * step.GetYRot() / 256.0f);
570 entity->SetPitch(360.0f * step.GetXRot() / 256.0f);
571 }
572#endif
573}
#define LOG_WARNING(osstream)
Definition Logger.hpp:44
void SetModifier(const ModifierKey &key, const Modifier &modifier)
virtual void Handle(ProtocolCraft::ClientboundLoginPacket &packet) override
std::shared_ptr< LocalPlayer > GetLocalPlayer()
std::shared_ptr< LocalPlayer > local_player
std::shared_mutex entity_manager_mutex
Utilities::ScopeLockedWrapper< const std::unordered_map< int, std::shared_ptr< Entity > >, std::shared_mutex, std::shared_lock > GetEntities() const
Get a read-only locked version of all the loaded entities (including local player)
std::unordered_map< int, std::shared_ptr< Entity > > entities
void AddEntity(const std::shared_ptr< Entity > &entity)
EntityManager(const std::shared_ptr< NetworkManager > &network_manager)
std::shared_ptr< Entity > GetEntity(const int id) const
static std::shared_ptr< Entity > CreateEntity(const EntityType type)
Definition Entity.cpp:1498
Mutex protected reference, will be locked until destroyed.
EquipmentSlot
Definition Enums.hpp:276
EntityEffectType
Definition Enums.hpp:318