the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at master 821 lines 28 kB view raw
1#include "stdafx.h" 2#include "TrackedEntity.h" 3#include "ServerPlayer.h" 4#include "PlayerConnection.h" 5#include "..\Minecraft.World\Mth.h" 6#include "..\Minecraft.World\net.minecraft.world.entity.h" 7#include "..\Minecraft.World\net.minecraft.world.entity.item.h" 8#include "..\Minecraft.World\net.minecraft.world.entity.monster.h" 9#include "..\Minecraft.World\net.minecraft.world.entity.player.h" 10#include "..\Minecraft.World\net.minecraft.world.entity.animal.h" 11#include "..\Minecraft.World\net.minecraft.world.entity.global.h" 12#include "..\Minecraft.World\net.minecraft.world.entity.projectile.h" 13#include "..\Minecraft.World\net.minecraft.network.packet.h" 14#include "..\Minecraft.World\net.minecraft.world.item.h" 15#include "..\Minecraft.World\net.minecraft.world.level.saveddata.h" 16#include "..\Minecraft.World\net.minecraft.world.entity.ai.attributes.h" 17#include "MinecraftServer.h" 18#include "ServerLevel.h" 19#include "PlayerList.h" 20#include "EntityTracker.h" 21#include "PlayerChunkMap.h" 22#include <qnet.h> 23 24TrackedEntity::TrackedEntity(shared_ptr<Entity> e, int range, int updateInterval, bool trackDelta) 25{ 26 // 4J added initialisers 27 xap = yap = zap = 0; 28 tickCount = 0; 29 xpu = ypu = zpu = 0; 30 updatedPlayerVisibility = false; 31 teleportDelay = 0; 32 moved = false; 33 wasRiding = false; 34 35 this->e = e; 36 this->range = range; 37 this->updateInterval = updateInterval; 38 this->trackDelta = trackDelta; 39 40 xp = Mth::floor(e->x * 32); 41 yp = Mth::floor(e->y * 32); 42 zp = Mth::floor(e->z * 32); 43 44 yRotp = Mth::floor(e->yRot * 256 / 360); 45 xRotp = Mth::floor(e->xRot * 256 / 360); 46 yHeadRotp = Mth::floor(e->getYHeadRot() * 256 / 360); 47} 48 49int c0a = 0, c0b = 0, c1a = 0, c1b = 0, c1c = 0, c2a = 0, c2b = 0; 50 51void TrackedEntity::tick(EntityTracker *tracker, vector<shared_ptr<Player> > *players) 52{ 53 moved = false; 54 if (!updatedPlayerVisibility || e->distanceToSqr(xpu, ypu, zpu) > 4 * 4) 55 { 56 xpu = e->x; 57 ypu = e->y; 58 zpu = e->z; 59 updatedPlayerVisibility = true; 60 moved = true; 61 updatePlayers(tracker, players); 62 } 63 64 if (lastRidingEntity != e->riding || (e->riding != NULL && tickCount % (SharedConstants::TICKS_PER_SECOND * 3) == 0)) 65 { 66 lastRidingEntity = e->riding; 67 broadcast(shared_ptr<SetEntityLinkPacket>(new SetEntityLinkPacket(SetEntityLinkPacket::RIDING, e, e->riding))); 68 } 69 70 // Moving forward special case for item frames 71 if (e->GetType()== eTYPE_ITEM_FRAME && tickCount % 10 == 0) 72 { 73 shared_ptr<ItemFrame> frame = dynamic_pointer_cast<ItemFrame> (e); 74 shared_ptr<ItemInstance> item = frame->getItem(); 75 76 if (item != NULL && item->getItem()->id == Item::map_Id && !e->removed) 77 { 78 shared_ptr<MapItemSavedData> data = Item::map->getSavedData(item, e->level); 79 for (AUTO_VAR(it,players->begin() ); it != players->end(); ++it) 80 { 81 shared_ptr<ServerPlayer> player = dynamic_pointer_cast<ServerPlayer>(*it); 82 data->tickCarriedBy(player, item); 83 84 if (!player->removed && player->connection && player->connection->countDelayedPackets() <= 5) 85 { 86 shared_ptr<Packet> packet = Item::map->getUpdatePacket(item, e->level, player); 87 if (packet != NULL) player->connection->send(packet); 88 } 89 } 90 } 91 92 shared_ptr<SynchedEntityData> entityData = e->getEntityData(); 93 if (entityData->isDirty()) 94 { 95 broadcastAndSend( shared_ptr<SetEntityDataPacket>( new SetEntityDataPacket(e->entityId, entityData, false) ) ); 96 } 97 } 98 else if (tickCount % updateInterval == 0 || e->hasImpulse || e->getEntityData()->isDirty()) 99 { 100 // 4J: Moved this as it's shared 101 int yRotn = Mth::floor(e->yRot * 256 / 360); 102 int xRotn = Mth::floor(e->xRot * 256 / 360); 103 104 // 4J: Changed rotation to be generally sent as a delta as well as position 105 int yRota = yRotn - yRotp; 106 int xRota = xRotn - xRotp; 107 108 if(e->riding == NULL) 109 { 110 teleportDelay++; 111 112 int xn = Mth::floor(e->x * 32.0); 113 int yn = Mth::floor(e->y * 32.0); 114 int zn = Mth::floor(e->z * 32.0); 115 116 int xa = xn - xp; 117 int ya = yn - yp; 118 int za = zn - zp; 119 120 shared_ptr<Packet> packet = nullptr; 121 122 // 4J - this pos flag used to be set based on abs(xn) etc. but that just seems wrong 123 bool pos = abs(xa) >= TOLERANCE_LEVEL || abs(ya) >= TOLERANCE_LEVEL || abs(za) >= TOLERANCE_LEVEL || (tickCount % (SharedConstants::TICKS_PER_SECOND * 3) == 0); 124 125 // Keep rotation deltas in +/- 180 degree range 126 while( yRota > 127 ) yRota -= 256; 127 while( yRota < -128 ) yRota += 256; 128 while( xRota > 127 ) xRota -= 256; 129 while( xRota < -128 ) xRota += 256; 130 131 bool rot = abs(yRota) >= TOLERANCE_LEVEL || abs(xRota) >= TOLERANCE_LEVEL; 132 133 // 4J: Modified the following check. It was originally added by Mojang to address 134 // certain unspecified issues with entity position. Turns out the issue effects a 135 // variety of different entities so we've left it in and just added the new exceptions 136 // (so far just players) 137 138 // 4J: Original comment follows 139 // TODO: Figure out how to fix this properly 140 // skip first tick since position is sent in addEntity packet 141 // FallingTile depends on this because it removes its source block in the first tick() 142 143 if (tickCount > 0 || e->instanceof(eTYPE_ARROW) || e->instanceof(eTYPE_PLAYER)) // 4J: Modifed, see above 144 { 145 if (xa < -128 || xa >= 128 || ya < -128 || ya >= 128 || za < -128 || za >= 128 || wasRiding 146 // 4J Stu - I fixed the initialisation of teleportDelay in the ctor, but we managed this far without out 147 // and would prefer not to have all the extra traffix so ignore it 148 // 4J Stu - Fix for #9579 - GAMEPLAY: Boats with a player in them slowly sink under the water over time, and with no player in them they float into the sky. 149 || (e->GetType() == eTYPE_BOAT && teleportDelay > 20 * 20) 150 ) 151 { 152 teleportDelay = 0; 153 packet = shared_ptr<TeleportEntityPacket>( new TeleportEntityPacket(e->entityId, xn, yn, zn, (byte) yRotn, (byte) xRotn) ); 154 // printf("%d: New teleport rot %d\n",e->entityId,yRotn); 155 yRotp = yRotn; 156 xRotp = xRotn; 157 } 158 else 159 { 160 if (pos && rot) 161 { 162 // 4J If the movement is small enough, and there's no xrot, then use the new smaller packets 163 if( ( xa >= -16 ) && ( xa <= 15 ) && 164 ( za >= -16 ) && ( za <= 15 ) && 165 ( ya >= -32 ) && ( ya <= 31 ) && 166 ( xRota == 0 )) 167 { 168 // Clamp rotations that are too big 169 if( yRota < -16 ) 170 { 171 yRota = -16; 172 yRotn = yRotp + yRota; 173 } 174 else if( yRota > 15 ) 175 { 176 yRota = 15; 177 yRotn = yRotp + yRota; 178 } 179 // 5 bits each for x & z, and 6 for y 180 packet = shared_ptr<MoveEntityPacketSmall>( new MoveEntityPacketSmall::PosRot(e->entityId, (char) xa, (char) ya, (char) za, (char) yRota, 0 ) ); 181 c0a++; 182 } 183 else 184 { 185 packet = shared_ptr<MoveEntityPacket>( new MoveEntityPacket::PosRot(e->entityId, (char) xa, (char) ya, (char) za, (char) yRota, (char) xRota) ); 186 // printf("%d: New posrot %d + %d = %d\n",e->entityId,yRotp,yRota,yRotn); 187 c0b++; 188 } 189 } 190 else if (pos) 191 { 192 // 4J If the movement is small enough, then use the new smaller packets 193 if( ( xa >= -8 ) && ( xa <= 7 ) && 194 ( za >= -8 ) && ( za <= 7 ) && 195 ( ya >= -16 ) && ( ya <= 15 ) ) 196 { 197 // 4 bits each for x & z, and 5 for y 198 packet = shared_ptr<MoveEntityPacketSmall>( new MoveEntityPacketSmall::Pos(e->entityId, (char) xa, (char) ya, (char) za) ); 199 c1a++; 200 } 201 202 else if( ( xa >= -16 ) && ( xa <= 15 ) && 203 ( za >= -16 ) && ( za <= 15 ) && 204 ( ya >= -32 ) && ( ya <= 31 ) ) 205 { 206 // use the packet with small packet with rotation if we can - 5 bits each for x & z, and 6 for y - still a byte less than the alternative 207 packet = shared_ptr<MoveEntityPacketSmall>( new MoveEntityPacketSmall::PosRot(e->entityId, (char) xa, (char) ya, (char) za, 0, 0 )); 208 c1b++; 209 } 210 else 211 { 212 packet = shared_ptr<MoveEntityPacket>( new MoveEntityPacket::Pos(e->entityId, (char) xa, (char) ya, (char) za) ); 213 c1c++; 214 } 215 } 216 else if (rot) 217 { 218 // 4J If there's no x rotation, then use the new smaller packet type 219 if( xRota == 0 ) 220 { 221 // Clamp rotations that are too big 222 if( yRota < -16 ) 223 { 224 yRota = -16; 225 yRotn = yRotp + yRota; 226 } 227 else if( yRota > 15 ) 228 { 229 yRota = 15; 230 yRotn = yRotp + yRota; 231 } 232 packet = shared_ptr<MoveEntityPacketSmall>( new MoveEntityPacketSmall::Rot(e->entityId, (char) yRota, 0) ); 233 c2a++; 234 } 235 else 236 { 237 // printf("%d: New rot %d + %d = %d\n",e->entityId,yRotp,yRota,yRotn); 238 packet = shared_ptr<MoveEntityPacket>( new MoveEntityPacket::Rot(e->entityId, (char) yRota, (char) xRota) ); 239 c2b++; 240 } 241 } 242 } 243 } 244 245 if (trackDelta) 246 { 247 double xad = e->xd - xap; 248 double yad = e->yd - yap; 249 double zad = e->zd - zap; 250 251 double max = 0.02; 252 253 double diff = xad * xad + yad * yad + zad * zad; 254 255 if (diff > max * max || (diff > 0 && e->xd == 0 && e->yd == 0 && e->zd == 0)) 256 { 257 xap = e->xd; 258 yap = e->yd; 259 zap = e->zd; 260 broadcast( shared_ptr<SetEntityMotionPacket>( new SetEntityMotionPacket(e->entityId, xap, yap, zap) ) ); 261 } 262 263 } 264 265 if (packet != NULL) 266 { 267 broadcast(packet); 268 } 269 270 sendDirtyEntityData(); 271 272 if (pos) 273 { 274 xp = xn; 275 yp = yn; 276 zp = zn; 277 } 278 if (rot) 279 { 280 yRotp = yRotn; 281 xRotp = xRotn; 282 } 283 284 wasRiding = false; 285 } 286 else 287 { 288 bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL; 289 if (rot) 290 { 291 // 4J: Changed this to use deltas 292 broadcast( shared_ptr<MoveEntityPacket>( new MoveEntityPacket::Rot(e->entityId, (byte) yRota, (byte) xRota)) ); 293 yRotp = yRotn; 294 xRotp = xRotn; 295 } 296 297 xp = Mth::floor(e->x * 32.0); 298 yp = Mth::floor(e->y * 32.0); 299 zp = Mth::floor(e->z * 32.0); 300 301 sendDirtyEntityData(); 302 303 wasRiding = true; 304 } 305 306 int yHeadRot = Mth::floor(e->getYHeadRot() * 256 / 360); 307 if (abs(yHeadRot - yHeadRotp) >= TOLERANCE_LEVEL) 308 { 309 broadcast(shared_ptr<RotateHeadPacket>( new RotateHeadPacket(e->entityId, (byte) yHeadRot))); 310 yHeadRotp = yHeadRot; 311 } 312 313 e->hasImpulse = false; 314 } 315 316 tickCount++; 317 318 if (e->hurtMarked) 319 { 320 // broadcast(new AnimatePacket(e, AnimatePacket.HURT)); 321 broadcastAndSend( shared_ptr<SetEntityMotionPacket>( new SetEntityMotionPacket(e) ) ); 322 e->hurtMarked = false; 323 } 324 325} 326 327void TrackedEntity::sendDirtyEntityData() 328{ 329 shared_ptr<SynchedEntityData> entityData = e->getEntityData(); 330 if (entityData->isDirty()) 331 { 332 broadcastAndSend( shared_ptr<SetEntityDataPacket>( new SetEntityDataPacket(e->entityId, entityData, false)) ); 333 } 334 335 if ( e->instanceof(eTYPE_LIVINGENTITY) ) 336 { 337 shared_ptr<LivingEntity> living = dynamic_pointer_cast<LivingEntity>(e); 338 ServersideAttributeMap *attributeMap = (ServersideAttributeMap *) living->getAttributes(); 339 unordered_set<AttributeInstance *> *attributes = attributeMap->getDirtyAttributes(); 340 341 if (!attributes->empty()) 342 { 343 broadcastAndSend(shared_ptr<UpdateAttributesPacket>( new UpdateAttributesPacket(e->entityId, attributes)) ); 344 } 345 346 attributes->clear(); 347 } 348} 349 350void TrackedEntity::broadcast(shared_ptr<Packet> packet) 351{ 352 if( Packet::canSendToAnyClient( packet ) ) 353 { 354 // 4J-PB - due to the knockback on a player being hit, we need to send to all players, but limit the network traffic here to players that have not already had it sent to their system 355 vector< shared_ptr<ServerPlayer> > sentTo; 356 357 // 4J - don't send to a player we've already sent this data to that shares the same machine. 358 // EntityMotionPacket used to limit themselves to sending once to each machine 359 // by only sending to the primary player on each machine. This was causing trouble for split screen 360 // as only the primary player would get a knockback velocity. Now these packets can be sent to any 361 // player, but we try to restrict the network impact this has by not resending to the one machine 362 363 for( AUTO_VAR(it, seenBy.begin()); it != seenBy.end(); it++ ) 364 { 365 shared_ptr<ServerPlayer> player = *it; 366 bool dontSend = false; 367 if( sentTo.size() ) 368 { 369 INetworkPlayer *thisPlayer =player->connection->getNetworkPlayer(); 370 if( thisPlayer == NULL ) 371 { 372 dontSend = true; 373 } 374 else 375 { 376 for(unsigned int j = 0; j < sentTo.size(); j++ ) 377 { 378 shared_ptr<ServerPlayer> player2 = sentTo[j]; 379 INetworkPlayer *otherPlayer = player2->connection->getNetworkPlayer(); 380 if( otherPlayer != NULL && thisPlayer->IsSameSystem(otherPlayer) ) 381 { 382 dontSend = true; 383 // #ifdef _DEBUG 384 // shared_ptr<SetEntityMotionPacket> emp= dynamic_pointer_cast<SetEntityMotionPacket> (packet); 385 // if(emp!=NULL) 386 // { 387 // app.DebugPrintf("Not sending this SetEntityMotionPacket to player - it's already been sent to a player on their console\n"); 388 // } 389 // #endif 390 } 391 } 392 } 393 } 394 if( dontSend ) 395 { 396 continue; 397 } 398 399 400 (*it)->connection->send(packet); 401 sentTo.push_back(player); 402 } 403 } 404 else 405 { 406 // This packet hasn't got canSendToAnyClient set, so just send to everyone here, and it 407 408 for( AUTO_VAR(it, seenBy.begin()); it != seenBy.end(); it++ ) 409 { 410 (*it)->connection->send(packet); 411 } 412 } 413} 414 415void TrackedEntity::broadcastAndSend(shared_ptr<Packet> packet) 416{ 417 vector< shared_ptr<ServerPlayer> > sentTo; 418 broadcast(packet); 419 shared_ptr<ServerPlayer> sp = e->instanceof(eTYPE_SERVERPLAYER) ? dynamic_pointer_cast<ServerPlayer>(e) : nullptr; 420 if (sp != NULL && sp->connection) 421 { 422 sp->connection->send(packet); 423 } 424} 425 426void TrackedEntity::broadcastRemoved() 427{ 428 for( AUTO_VAR(it, seenBy.begin()); it != seenBy.end(); it++ ) 429 { 430 (*it)->entitiesToRemove.push_back(e->entityId); 431 } 432} 433 434void TrackedEntity::removePlayer(shared_ptr<ServerPlayer> sp) 435{ 436 AUTO_VAR(it, seenBy.find( sp )); 437 if( it != seenBy.end() ) 438 { 439 sp->entitiesToRemove.push_back(e->entityId); 440 seenBy.erase( it ); 441 } 442} 443 444// 4J-JEV: Added for code reuse. 445TrackedEntity::eVisibility TrackedEntity::isVisible(EntityTracker *tracker, shared_ptr<ServerPlayer> sp, bool forRider) 446{ 447 // 4J Stu - We call update players when the entity has moved more than a certain amount at the start of it's tick 448 // Before this call we set xpu, ypu and zpu to the entities new position, but xp,yp and zp are the old position until later in the tick. 449 // Therefore we should use the new position for visibility checks 450 double xd = sp->x - xpu; //xp / 32; 451 double zd = sp->z - zpu; //zp / 32; 452 453 // 4J Stu - Fix for loading a player who is currently riding something (e.g. a horse) 454 if(e->forcedLoading) 455 { 456 xd = sp->x - xp / 32; 457 zd = sp->z - zp / 32; 458 } 459 460 int playersRange = range; 461 if( playersRange > TRACKED_ENTITY_MINIMUM_VIEW_DISTANCE ) 462 { 463 playersRange -= sp->getPlayerViewDistanceModifier(); 464 } 465 466 bool bVisible = xd >= -playersRange && xd <= playersRange && zd >= -playersRange && zd <= playersRange; 467 bool canBeSeenBy = canBySeenBy(sp); 468 469 // 4J - added. Try and find other players who are in the same dimension as this one and on the same machine, and extend our visibility 470 // so things are consider visible to this player if they are near the other one. This is because we only send entity tracking info to 471 // players who canReceiveAllPackets(). 472 if(!bVisible) 473 { 474 MinecraftServer *server = MinecraftServer::getInstance(); 475 INetworkPlayer *thisPlayer = sp->connection->getNetworkPlayer(); 476 if( thisPlayer ) 477 { 478 for( unsigned int i = 0; i < server->getPlayers()->players.size(); i++ ) 479 { 480 // Consider extra players, but not if they are the entity we are tracking, or the player we've been passed as input, or in another dimension 481 shared_ptr<ServerPlayer> ep = server->getPlayers()->players[i]; 482 if( ep == sp ) continue; 483 if( ep == e ) continue; 484 if( ep->dimension != sp->dimension ) continue; 485 486 INetworkPlayer * otherPlayer = ep->connection->getNetworkPlayer(); 487 if( otherPlayer != NULL && thisPlayer->IsSameSystem(otherPlayer) ) 488 { 489 // 4J Stu - We call update players when the entity has moved more than a certain amount at the start of it's tick 490 // Before this call we set xpu, ypu and zpu to the entities new position, but xp,yp and zp are the old position until later in the tick. 491 // Therefore we should use the new position for visibility checks 492 double xd = ep->x - xpu; //xp / 32; 493 double zd = ep->z - zpu; //zp / 32; 494 bVisible |= ( xd >= -playersRange && xd <= playersRange && zd >= -playersRange && zd <= playersRange ); 495 canBeSeenBy |= canBySeenBy(ep); 496 } 497 } 498 } 499 } 500 501 // 4J Stu - We need to ensure that we send the mount before the rider, so check that the player has been added to the seenBy list 502 if(forRider) 503 { 504 canBeSeenBy = canBeSeenBy && (seenBy.find(sp) != seenBy.end()); 505 } 506 507 // 4J-JEV: ADDED! An entities mount has to be visible before the entity visible, 508 // this is to ensure that the mount is already in the client's game when the rider is added. 509 if (canBeSeenBy && bVisible && e->riding != NULL) 510 { 511 return tracker->getTracker(e->riding)->isVisible(tracker, sp, true); 512 } 513 else if (canBeSeenBy && bVisible) return eVisibility_SeenAndVisible; 514 else if (bVisible) return eVisibility_IsVisible; 515 else return eVisibility_NotVisible; 516} 517 518void TrackedEntity::updatePlayer(EntityTracker *tracker, shared_ptr<ServerPlayer> sp) 519{ 520 if (sp == e) return; 521 522 eVisibility visibility = this->isVisible(tracker, sp); 523 524 if ( visibility == eVisibility_SeenAndVisible 525 && (seenBy.find(sp) == seenBy.end() || e->forcedLoading)) 526 { 527 seenBy.insert(sp); 528 shared_ptr<Packet> packet = getAddEntityPacket(); 529 sp->connection->send(packet); 530 531 xap = e->xd; 532 yap = e->yd; 533 zap = e->zd; 534 535 if ( e->instanceof(eTYPE_PLAYER) ) 536 { 537 shared_ptr<Player> plr = dynamic_pointer_cast<Player>(e); 538 app.DebugPrintf( "TrackedEntity:: Player '%ls' is now visible to player '%ls', %s.\n", 539 plr->name.c_str(), sp->name.c_str(), 540 (e->riding==NULL?"not riding minecart":"in minecart") 541 ); 542 } 543 544 bool isAddMobPacket = dynamic_pointer_cast<AddMobPacket>(packet) != NULL; 545 546 // 4J Stu brought forward to fix when Item Frames 547 if (!e->getEntityData()->isEmpty() && !isAddMobPacket) 548 { 549 sp->connection->send(shared_ptr<SetEntityDataPacket>( new SetEntityDataPacket(e->entityId, e->getEntityData(), true))); 550 } 551 552 if ( e->instanceof(eTYPE_LIVINGENTITY) ) 553 { 554 shared_ptr<LivingEntity> living = dynamic_pointer_cast<LivingEntity>(e); 555 ServersideAttributeMap *attributeMap = (ServersideAttributeMap *) living->getAttributes(); 556 unordered_set<AttributeInstance *> *attributes = attributeMap->getSyncableAttributes(); 557 558 if (!attributes->empty()) 559 { 560 sp->connection->send(shared_ptr<UpdateAttributesPacket>( new UpdateAttributesPacket(e->entityId, attributes)) ); 561 } 562 delete attributes; 563 } 564 565 if (trackDelta && !isAddMobPacket) 566 { 567 sp->connection->send( shared_ptr<SetEntityMotionPacket>( new SetEntityMotionPacket(e->entityId, e->xd, e->yd, e->zd) ) ); 568 } 569 570 if (e->riding != NULL) 571 { 572 sp->connection->send(shared_ptr<SetEntityLinkPacket>(new SetEntityLinkPacket(SetEntityLinkPacket::RIDING, e, e->riding))); 573 } 574 if ( e->instanceof(eTYPE_MOB) && dynamic_pointer_cast<Mob>(e)->getLeashHolder() != NULL) 575 { 576 sp->connection->send( shared_ptr<SetEntityLinkPacket>( new SetEntityLinkPacket(SetEntityLinkPacket::LEASH, e, dynamic_pointer_cast<Mob>(e)->getLeashHolder())) ); 577 } 578 579 if ( e->instanceof(eTYPE_LIVINGENTITY) ) 580 { 581 for (int i = 0; i < 5; i++) 582 { 583 shared_ptr<ItemInstance> item = dynamic_pointer_cast<LivingEntity>(e)->getCarried(i); 584 if(item != NULL) sp->connection->send( shared_ptr<SetEquippedItemPacket>( new SetEquippedItemPacket(e->entityId, i, item) ) ); 585 } 586 } 587 588 if ( e->instanceof(eTYPE_PLAYER) ) 589 { 590 shared_ptr<Player> spe = dynamic_pointer_cast<Player>(e); 591 if (spe->isSleeping()) 592 { 593 sp->connection->send( shared_ptr<EntityActionAtPositionPacket>( new EntityActionAtPositionPacket(e, EntityActionAtPositionPacket::START_SLEEP, Mth::floor(e->x), Mth::floor(e->y), Mth::floor(e->z)) ) ); 594 } 595 } 596 597 if ( e->instanceof(eTYPE_LIVINGENTITY) ) 598 { 599 shared_ptr<LivingEntity> mob = dynamic_pointer_cast<LivingEntity>(e); 600 vector<MobEffectInstance *> *activeEffects = mob->getActiveEffects(); 601 for(AUTO_VAR(it, activeEffects->begin()); it != activeEffects->end(); ++it) 602 { 603 MobEffectInstance *effect = *it; 604 605 sp->connection->send(shared_ptr<UpdateMobEffectPacket>( new UpdateMobEffectPacket(e->entityId, effect) ) ); 606 } 607 delete activeEffects; 608 } 609 } 610 else if (visibility == eVisibility_NotVisible) 611 { 612 AUTO_VAR(it, seenBy.find(sp)); 613 if (it != seenBy.end()) 614 { 615 seenBy.erase(it); 616 sp->entitiesToRemove.push_back(e->entityId); 617 } 618 } 619 620} 621 622bool TrackedEntity::canBySeenBy(shared_ptr<ServerPlayer> player) 623{ 624 // 4J - for some reason this isn't currently working, and is causing players to not appear until we are really close to them. Not sure 625 // what the conflict is between the java & our version, but removing for now as it is causing issues and we shouldn't *really* need it 626 // TODO - investigate further 627 628 return true; 629 // return player->getLevel()->getChunkMap()->isPlayerIn(player, e->xChunk, e->zChunk); 630} 631 632void TrackedEntity::updatePlayers(EntityTracker *tracker, vector<shared_ptr<Player> > *players) 633{ 634 for (unsigned int i = 0; i < players->size(); i++) 635 { 636 updatePlayer(tracker, dynamic_pointer_cast<ServerPlayer>( players->at(i) ) ); 637 } 638} 639 640shared_ptr<Packet> TrackedEntity::getAddEntityPacket() 641{ 642 if (e->removed) 643 { 644 app.DebugPrintf("Fetching addPacket for removed entity - %ls\n", e->getAName().c_str()); 645 } 646 647 // 4J-PB - replacing with a switch, rather than tons of ifs 648 if (dynamic_pointer_cast<Creature>(e) != NULL) 649 { 650 yHeadRotp = Mth::floor(e->getYHeadRot() * 256 / 360); 651 return shared_ptr<AddMobPacket>( new AddMobPacket(dynamic_pointer_cast<Mob>(e), yRotp, xRotp, xp, yp, zp, yHeadRotp) ); 652 } 653 654 if (e->instanceof(eTYPE_ITEMENTITY)) 655 { 656 shared_ptr<AddEntityPacket> packet = shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::ITEM, 1, yRotp, xRotp, xp, yp, zp) ); 657 return packet; 658 } 659 else if (e->instanceof(eTYPE_SERVERPLAYER)) 660 { 661 shared_ptr<ServerPlayer> player = dynamic_pointer_cast<ServerPlayer>(e); 662 663 PlayerUID xuid = INVALID_XUID; 664 PlayerUID OnlineXuid = INVALID_XUID; 665 if( player != NULL ) 666 { 667 xuid = player->getXuid(); 668 OnlineXuid = player->getOnlineXuid(); 669 } 670 // 4J Added yHeadRotp param to fix #102563 - TU12: Content: Gameplay: When one of the Players is idle for a few minutes his head turns 180 degrees. 671 return shared_ptr<AddPlayerPacket>( new AddPlayerPacket( player, xuid, OnlineXuid, xp, yp, zp, yRotp, xRotp, yHeadRotp ) ); 672 } 673 else if (e->instanceof(eTYPE_MINECART)) 674 { 675 shared_ptr<Minecart> minecart = dynamic_pointer_cast<Minecart>(e); 676 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::MINECART, minecart->getType(), yRotp, xRotp, xp, yp, zp) ); 677 } 678 else if (e->instanceof(eTYPE_BOAT)) 679 { 680 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::BOAT, yRotp, xRotp, xp, yp, zp) ); 681 } 682 else if (e->instanceof(eTYPE_ENDERDRAGON)) 683 { 684 yHeadRotp = Mth::floor(e->getYHeadRot() * 256 / 360); 685 return shared_ptr<AddMobPacket>( new AddMobPacket(dynamic_pointer_cast<LivingEntity>(e), yRotp, xRotp, xp, yp, zp, yHeadRotp ) ); 686 } 687 else if (e->instanceof(eTYPE_FISHINGHOOK)) 688 { 689 shared_ptr<Entity> owner = dynamic_pointer_cast<FishingHook>(e)->owner; 690 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::FISH_HOOK, owner != NULL ? owner->entityId : e->entityId, yRotp, xRotp, xp, yp, zp) ); 691 } 692 else if (e->instanceof(eTYPE_ARROW)) 693 { 694 shared_ptr<Entity> owner = (dynamic_pointer_cast<Arrow>(e))->owner; 695 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::ARROW, owner != NULL ? owner->entityId : e->entityId, yRotp, xRotp, xp, yp, zp) ); 696 } 697 else if (e->instanceof(eTYPE_SNOWBALL)) 698 { 699 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::SNOWBALL, yRotp, xRotp, xp, yp, zp) ); 700 } 701 else if (e->instanceof(eTYPE_THROWNPOTION)) 702 { 703 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::THROWN_POTION, ((dynamic_pointer_cast<ThrownPotion>(e))->getPotionValue()), yRotp, xRotp, xp, yp, zp)); 704 } 705 else if (e->instanceof(eTYPE_THROWNEXPBOTTLE)) 706 { 707 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::THROWN_EXPBOTTLE, yRotp, xRotp, xp, yp, zp) ); 708 } 709 else if (e->instanceof(eTYPE_THROWNENDERPEARL)) 710 { 711 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::THROWN_ENDERPEARL, yRotp, xRotp, xp, yp, zp) ); 712 } 713 else if (e->instanceof(eTYPE_EYEOFENDERSIGNAL)) 714 { 715 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::EYEOFENDERSIGNAL, yRotp, xRotp, xp, yp, zp) ); 716 } 717 else if (e->instanceof(eTYPE_FIREWORKS_ROCKET)) 718 { 719 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::FIREWORKS, yRotp, xRotp, xp, yp, zp) ); 720 } 721 else if (e->instanceof(eTYPE_FIREBALL)) 722 { 723 eINSTANCEOF classType = e->GetType(); 724 int type = AddEntityPacket::FIREBALL; 725 if (classType == eTYPE_SMALL_FIREBALL) 726 { 727 type = AddEntityPacket::SMALL_FIREBALL; 728 } 729 else if (classType == eTYPE_DRAGON_FIREBALL) 730 { 731 type = AddEntityPacket::DRAGON_FIRE_BALL; 732 } 733 else if (classType == eTYPE_WITHER_SKULL) 734 { 735 type = AddEntityPacket::WITHER_SKULL; 736 } 737 738 shared_ptr<Fireball> fb = dynamic_pointer_cast<Fireball>(e); 739 shared_ptr<AddEntityPacket> aep = nullptr; 740 if (fb->owner != NULL) 741 { 742 aep = shared_ptr<AddEntityPacket>( new AddEntityPacket(e, type, fb->owner->entityId, yRotp, xRotp, xp, yp, zp) ); 743 } 744 else 745 { 746 aep = shared_ptr<AddEntityPacket>( new AddEntityPacket(e, type, 0, yRotp, xRotp, xp, yp, zp) ); 747 } 748 aep->xa = (int) (fb->xPower * 8000); 749 aep->ya = (int) (fb->yPower * 8000); 750 aep->za = (int) (fb->zPower * 8000); 751 return aep; 752 } 753 else if (e->instanceof(eTYPE_THROWNEGG)) 754 { 755 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::EGG, yRotp, xRotp, xp, yp, zp) ); 756 } 757 else if (e->instanceof(eTYPE_PRIMEDTNT)) 758 { 759 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::PRIMED_TNT, yRotp, xRotp, xp, yp, zp) ); 760 } 761 else if (e->instanceof(eTYPE_ENDER_CRYSTAL)) 762 { 763 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::ENDER_CRYSTAL, yRotp, xRotp, xp, yp, zp) ); 764 } 765 else if (e->instanceof(eTYPE_FALLINGTILE)) 766 { 767 shared_ptr<FallingTile> ft = dynamic_pointer_cast<FallingTile>(e); 768 return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::FALLING, ft->tile | (ft->data << 16), yRotp, xRotp, xp, yp, zp) ); 769 } 770 else if (e->instanceof(eTYPE_PAINTING)) 771 { 772 return shared_ptr<AddPaintingPacket>( new AddPaintingPacket(dynamic_pointer_cast<Painting>(e)) ); 773 } 774 else if (e->instanceof(eTYPE_ITEM_FRAME)) 775 { 776 shared_ptr<ItemFrame> frame = dynamic_pointer_cast<ItemFrame>(e); 777 778 { 779 780 int ix= (int)frame->xTile; 781 int iy= (int)frame->yTile; 782 int iz= (int)frame->zTile; 783 app.DebugPrintf("eTYPE_ITEM_FRAME xyz %d,%d,%d\n",ix,iy,iz); 784 } 785 786 shared_ptr<AddEntityPacket> packet = shared_ptr<AddEntityPacket>(new AddEntityPacket(e, AddEntityPacket::ITEM_FRAME, frame->dir, yRotp, xRotp, xp, yp, zp)); 787 packet->x = Mth::floor(frame->xTile * 32.0f); 788 packet->y = Mth::floor(frame->yTile * 32.0f); 789 packet->z = Mth::floor(frame->zTile * 32.0f); 790 return packet; 791 } 792 else if (e->instanceof(eTYPE_LEASHFENCEKNOT)) 793 { 794 shared_ptr<LeashFenceKnotEntity> knot = dynamic_pointer_cast<LeashFenceKnotEntity>(e); 795 shared_ptr<AddEntityPacket> packet = shared_ptr<AddEntityPacket>(new AddEntityPacket(e, AddEntityPacket::LEASH_KNOT, yRotp, xRotp, xp, yp, zp) ); 796 packet->x = Mth::floor((float)knot->xTile * 32); 797 packet->y = Mth::floor((float)knot->yTile * 32); 798 packet->z = Mth::floor((float)knot->zTile * 32); 799 return packet; 800 } 801 else if (e->instanceof(eTYPE_EXPERIENCEORB)) 802 { 803 return shared_ptr<AddExperienceOrbPacket>( new AddExperienceOrbPacket(dynamic_pointer_cast<ExperienceOrb>(e)) ); 804 } 805 else 806 { 807 assert(false); 808 } 809 810 return nullptr; 811} 812 813void TrackedEntity::clear(shared_ptr<ServerPlayer> sp) 814{ 815 AUTO_VAR(it, seenBy.find(sp)); 816 if (it != seenBy.end()) 817 { 818 seenBy.erase(it); 819 sp->entitiesToRemove.push_back(e->entityId); 820 } 821}