Botcraft 1.21.5
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
161 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
162 entities[packet.GetEntityId()] = entity;
163 }
164
165#if PROTOCOL_VERSION < 759 /* < 1.19 */
166 void EntityManager::Handle(ProtocolCraft::ClientboundAddMobPacket& packet)
167 {
168 std::shared_ptr<Entity> entity = Entity::CreateEntity(static_cast<EntityType>(packet.GetType()));
169
170 entity->SetEntityID(packet.GetEntityId());
171 entity->SetX(packet.GetX());
172 entity->SetY(packet.GetY());
173 entity->SetZ(packet.GetZ());
174 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
175 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
176 entity->SetUUID(packet.GetUuid());
177
178 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
179 entities[packet.GetEntityId()] = entity;
180 }
181#endif
182
183#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
184 void EntityManager::Handle(ProtocolCraft::ClientboundAddExperienceOrbPacket& packet)
185 {
186 std::shared_ptr<Entity> entity = Entity::CreateEntity(EntityType::ExperienceOrb);
187
188 entity->SetEntityID(packet.GetEntityId());
189 entity->SetX(packet.GetX());
190 entity->SetY(packet.GetY());
191 entity->SetZ(packet.GetZ());
192 // What do we do with the xp value?
193 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
194 entities[packet.GetEntityId()] = entity;
195 }
196#endif
197
198#if PROTOCOL_VERSION < 721 /* < 1.16 */
199 void EntityManager::Handle(ProtocolCraft::ClientboundAddGlobalEntityPacket& packet)
200 {
201 std::shared_ptr<Entity> entity = Entity::CreateEntity(static_cast<EntityType>(packet.GetType()));
202
203 entity->SetEntityID(packet.GetEntityId());
204 entity->SetX(packet.GetX());
205 entity->SetY(packet.GetY());
206 entity->SetZ(packet.GetZ());
207
208 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
209 entities[packet.GetEntityId()] = entity;
210 }
211#endif
212
213#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
214 void EntityManager::Handle(ProtocolCraft::ClientboundAddPlayerPacket& packet)
215 {
216 std::shared_ptr<Entity> entity = nullptr;
217
218 {
219 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
220 auto it = entities.find(packet.GetEntityId());
221 if (it == entities.end())
222 {
224 entities[packet.GetEntityId()] = entity;
225 }
226 else
227 {
228 entity = it->second;
229 }
230 }
231
232 entity->SetEntityID(packet.GetEntityId());
233 entity->SetPosition(Vector3<double>(
234 packet.GetX(),
235 packet.GetY(),
236 packet.GetZ()
237 ));
238 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
239 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
240 entity->SetUUID(packet.GetPlayerId());
241 }
242#endif
243
245 {
246 local_player->SetHealth(packet.GetHealth());
247 local_player->SetFood(packet.GetFood());
248 local_player->SetFoodSaturation(packet.GetFoodSaturation());
249 }
250
252 {
253 std::shared_ptr<Entity> entity = nullptr;
254
255 {
256 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
257 auto it = entities.find(packet.GetEntityId());
258 if (it != entities.end())
259 {
260 entity = it->second;
261 }
262 }
263
264 if (entity != nullptr)
265 {
266#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
267 entity->SetPosition(Vector3<double>(
268 packet.GetX(),
269 packet.GetY(),
270 packet.GetZ()
271 ));
272 entity->SetYaw(360.0f * packet.GetYRot() / 256.0f);
273 entity->SetPitch(360.0f * packet.GetXRot() / 256.0f);
274#else
275 entity->SetPosition(Vector3<double>(
276 packet.GetRelatives() & (1 << 0) ? entity->GetX() + packet.GetChange().GetPosition()[0] : packet.GetChange().GetPosition()[0],
277 packet.GetRelatives() & (1 << 1) ? entity->GetY() + packet.GetChange().GetPosition()[1] : packet.GetChange().GetPosition()[1],
278 packet.GetRelatives() & (1 << 2) ? entity->GetZ() + packet.GetChange().GetPosition()[2] : packet.GetChange().GetPosition()[2]
279 ));
280 entity->SetYaw(packet.GetRelatives() & (1 << 3) ? entity->GetYaw() + packet.GetChange().GetYRot() : packet.GetChange().GetYRot());
281 entity->SetPitch(packet.GetRelatives() & (1 << 4) ? entity->GetPitch() + packet.GetChange().GetXRot() : packet.GetChange().GetXRot());
282#endif
283 entity->SetOnGround(packet.GetOnGround());
284 }
285 }
286
288 {
289 local_player->SetAbilitiesFlags(packet.GetFlags());
290 local_player->SetFlyingSpeed(packet.GetFlyingSpeed());
291 local_player->SetWalkingSpeed(packet.GetWalkingSpeed());
292 }
293
294#if PROTOCOL_VERSION == 755 /* 1.17 */
295 void EntityManager::Handle(ProtocolCraft::ClientboundRemoveEntityPacket& packet)
296 {
297 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
298 entities.erase(packet.GetEntityId());
299 }
300#else
302 {
303 std::scoped_lock<std::shared_mutex> lock(entity_manager_mutex);
304 for (int i = 0; i < packet.GetEntityIds().size(); ++i)
305 {
306 entities.erase(packet.GetEntityIds()[i]);
307 }
308 }
309#endif
310
312 {
313#if PROTOCOL_VERSION < 764 /* < 1.20.2 */
314 local_player->SetGameMode(static_cast<GameType>(packet.GetPlayerGameType()));
315#else
316 local_player->SetGameMode(static_cast<GameType>(packet.GetCommonPlayerSpawnInfo().GetGameType()));
317#endif
318 }
319
321 {
322 switch (packet.GetType())
323 {
324 case 3: // CHANGE_GAME_MODE
325 local_player->SetGameMode(static_cast<GameType>(packet.GetParam()));
326 break;
327 default:
328 break;
329 }
330 }
331
333 {
334 std::shared_ptr<Entity> entity = nullptr;
335
336 {
337 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
338 auto it = entities.find(packet.GetEntityId());
339 if (it != entities.end())
340 {
341 entity = it->second;
342 }
343 }
344
345 if (entity == nullptr)
346 {
347 LOG_WARNING("Trying to load metadata in unexisting entity");
348 }
349 else
350 {
351 entity->LoadMetadataFromRawArray(packet.GetPackedItems());
352 }
353 }
354
356 {
357 std::shared_ptr<Entity> entity = nullptr;
358
359 {
360 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
361 auto it = entities.find(packet.GetEntityId());
362 if (it != entities.end())
363 {
364 entity = it->second;
365 }
366 }
367
368 if (entity == nullptr)
369 {
370 LOG_WARNING("Trying to set speed of an unexisting entity");
371 }
372 else
373 {
374 // Packet data is in 1/8000 of block per tick, so convert it back to block/tick
375 entity->SetSpeed(Vector3<double>(packet.GetXA(), packet.GetYA(), packet.GetZA()) / 8000.0);
376 }
377 }
378
380 {
381 std::shared_ptr<Entity> entity = nullptr;
382
383 {
384 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
385 auto it = entities.find(packet.GetEntityId());
386 if (it != entities.end())
387 {
388 entity = it->second;
389 }
390 }
391
392 if (entity == nullptr)
393 {
394 LOG_WARNING("Trying to set equipment of an unexisting entity");
395 }
396 else
397 {
398#if PROTOCOL_VERSION > 730 /* > 1.15.2 */
399 for (auto& p : packet.GetSlots())
400 {
401 entity->SetEquipment(static_cast<EquipmentSlot>(p.first), p.second);
402 }
403#else
404 entity->SetEquipment(static_cast<EquipmentSlot>(packet.GetSlot().first), packet.GetSlot().second);
405#endif
406 }
407 }
408
410 {
411 std::shared_ptr<Entity> entity = nullptr;
412
413 {
414 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
415 auto it = entities.find(packet.GetEntityId());
416 if (it != entities.end())
417 {
418 entity = it->second;
419 }
420 }
421
422 if (entity == nullptr)
423 {
424 LOG_WARNING("Trying to set attributes of an unexisting entity");
425 }
426 else if (!entity->IsLivingEntity())
427 {
428 LOG_WARNING("Trying to set attributes of a non LivingEntity");
429 }
430 else
431 {
432 std::shared_ptr<LivingEntity> living_entity = std::dynamic_pointer_cast<LivingEntity>(entity);
433 for (const auto& a : packet.GetAttributes())
434 {
435#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
436 const EntityAttribute::Type type = static_cast<EntityAttribute::Type>(a.GetKey());
437#elif PROTOCOL_VERSION > 709 /* > 1.15.2 */
438 const EntityAttribute::Type type = EntityAttribute::StringToType(a.GetKey().GetFull());
439#else
440 const EntityAttribute::Type type = EntityAttribute::StringToType(a.GetKey());
441#endif
442 EntityAttribute attribute(type, a.GetValue());
443 for (const auto& m : a.GetModifiers())
444 {
445 attribute.SetModifier(
446#if PROTOCOL_VERSION < 767 /* < 1.21 */
447 m.GetUuid(),
448#else
449 m.GetId().GetFull(),
450#endif
451 EntityAttribute::Modifier{ m.GetAmount(), static_cast<EntityAttribute::Modifier::Operation>(m.GetOperation()) }
452 );
453 }
454 living_entity->AddAttribute(attribute);
455 }
456 }
457 }
458
460 {
461 std::shared_ptr<Entity> entity = nullptr;
462
463 {
464 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
465 auto it = entities.find(packet.GetEntityId());
466 if (it != entities.end())
467 {
468 entity = it->second;
469 }
470 }
471
472 if (entity == nullptr)
473 {
474 LOG_WARNING("Trying to set effect of an unexisting entity");
475 }
476 else
477 {
478 entity->AddEffect(EntityEffect {
479 static_cast<EntityEffectType>(packet.GetEffectId()), // type
480 static_cast<unsigned char>(packet.GetEffectAmplifier()), //amplifier
481 std::chrono::steady_clock::now() + std::chrono::milliseconds(50 * packet.GetEffectDurationTicks()) // end
482 });
483 }
484 }
485
487 {
488
489 std::shared_ptr<Entity> entity = nullptr;
490
491 {
492 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
493 auto it = entities.find(packet.GetEntityId());
494 if (it != entities.end())
495 {
496 entity = it->second;
497 }
498 }
499
500 if (entity == nullptr)
501 {
502 LOG_WARNING("Trying to remove effect of an unexisting entity");
503 }
504 else
505 {
506 entity->RemoveEffect(static_cast<EntityEffectType>(packet.GetEffect()));
507 }
508 }
509
510#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
512 {
513 std::shared_ptr<Entity> entity = nullptr;
514
515 {
516 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
517 auto it = entities.find(packet.GetEntityId());
518 if (it != entities.end())
519 {
520 entity = it->second;
521 }
522 }
523
524 if (entity != nullptr)
525 {
526 entity->SetPosition(packet.GetValues().GetPosition());
527 if (entity == local_player)
528 {
529 return;
530 }
531 entity->SetYaw(packet.GetValues().GetYRot());
532 entity->SetPitch(packet.GetValues().GetXRot());
533 entity->SetOnGround(packet.GetOnGround());
534 }
535 }
536
538 {
539 std::shared_ptr<Entity> entity = nullptr;
540
541 {
542 std::shared_lock<std::shared_mutex> lock(entity_manager_mutex);
543 auto it = entities.find(packet.GetEntityId());
544 if (it != entities.end())
545 {
546 entity = it->second;
547 }
548 }
549
550 if (entity == nullptr || !entity->IsAbstractMinecart())
551 {
552 return;
553 }
554
555 // Don't lerp, directly set the position to the last lerp step
556
557 const ProtocolCraft::MinecartBehaviorMinecartStep& step = packet.GetLerpSteps().back();
558 entity->SetPosition(step.GetPosition());
559 entity->SetYaw(360.0f * step.GetYRot() / 256.0f);
560 entity->SetPitch(360.0f * step.GetXRot() / 256.0f);
561 }
562#endif
563}
#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:1452
Mutex protected reference, will be locked until destroyed.
EquipmentSlot
Definition Enums.hpp:276
EntityEffectType
Definition Enums.hpp:315