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