Something went wrong. Try again.
the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
Something went wrong. Try again.
28 kB · 821 lines
C++
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822#include "stdafx.h"#include "TrackedEntity.h"#include "ServerPlayer.h"#include "PlayerConnection.h"#include "..\Minecraft.World\Mth.h"#include "..\Minecraft.World\net.minecraft.world.entity.h"#include "..\Minecraft.World\net.minecraft.world.entity.item.h"#include "..\Minecraft.World\net.minecraft.world.entity.monster.h"#include "..\Minecraft.World\net.minecraft.world.entity.player.h"#include "..\Minecraft.World\net.minecraft.world.entity.animal.h"#include "..\Minecraft.World\net.minecraft.world.entity.global.h"#include "..\Minecraft.World\net.minecraft.world.entity.projectile.h"#include "..\Minecraft.World\net.minecraft.network.packet.h"#include "..\Minecraft.World\net.minecraft.world.item.h"#include "..\Minecraft.World\net.minecraft.world.level.saveddata.h"#include "..\Minecraft.World\net.minecraft.world.entity.ai.attributes.h"#include "MinecraftServer.h"#include "ServerLevel.h"#include "PlayerList.h"#include "EntityTracker.h"#include "PlayerChunkMap.h"#include <qnet.h>
TrackedEntity::TrackedEntity(shared_ptr<Entity> e, int range, int updateInterval, bool trackDelta){ // 4J added initialisers xap = yap = zap = 0; tickCount = 0; xpu = ypu = zpu = 0; updatedPlayerVisibility = false; teleportDelay = 0; moved = false; wasRiding = false;
this->e = e; this->range = range; this->updateInterval = updateInterval; this->trackDelta = trackDelta;
xp = Mth::floor(e->x * 32); yp = Mth::floor(e->y * 32); zp = Mth::floor(e->z * 32);
yRotp = Mth::floor(e->yRot * 256 / 360); xRotp = Mth::floor(e->xRot * 256 / 360); yHeadRotp = Mth::floor(e->getYHeadRot() * 256 / 360);}
int c0a = 0, c0b = 0, c1a = 0, c1b = 0, c1c = 0, c2a = 0, c2b = 0;
void TrackedEntity::tick(EntityTracker *tracker, vector<shared_ptr<Player> > *players){ moved = false; if (!updatedPlayerVisibility || e->distanceToSqr(xpu, ypu, zpu) > 4 * 4) { xpu = e->x; ypu = e->y; zpu = e->z; updatedPlayerVisibility = true; moved = true; updatePlayers(tracker, players); }
if (lastRidingEntity != e->riding || (e->riding != NULL && tickCount % (SharedConstants::TICKS_PER_SECOND * 3) == 0)) { lastRidingEntity = e->riding; broadcast(shared_ptr<SetEntityLinkPacket>(new SetEntityLinkPacket(SetEntityLinkPacket::RIDING, e, e->riding))); }
// Moving forward special case for item frames if (e->GetType()== eTYPE_ITEM_FRAME && tickCount % 10 == 0) { shared_ptr<ItemFrame> frame = dynamic_pointer_cast<ItemFrame> (e); shared_ptr<ItemInstance> item = frame->getItem();
if (item != NULL && item->getItem()->id == Item::map_Id && !e->removed) { shared_ptr<MapItemSavedData> data = Item::map->getSavedData(item, e->level); for (AUTO_VAR(it,players->begin() ); it != players->end(); ++it) { shared_ptr<ServerPlayer> player = dynamic_pointer_cast<ServerPlayer>(*it); data->tickCarriedBy(player, item);
if (!player->removed && player->connection && player->connection->countDelayedPackets() <= 5) { shared_ptr<Packet> packet = Item::map->getUpdatePacket(item, e->level, player); if (packet != NULL) player->connection->send(packet); } } }
shared_ptr<SynchedEntityData> entityData = e->getEntityData(); if (entityData->isDirty()) { broadcastAndSend( shared_ptr<SetEntityDataPacket>( new SetEntityDataPacket(e->entityId, entityData, false) ) ); } } else if (tickCount % updateInterval == 0 || e->hasImpulse || e->getEntityData()->isDirty()) { // 4J: Moved this as it's shared int yRotn = Mth::floor(e->yRot * 256 / 360); int xRotn = Mth::floor(e->xRot * 256 / 360);
// 4J: Changed rotation to be generally sent as a delta as well as position int yRota = yRotn - yRotp; int xRota = xRotn - xRotp;
if(e->riding == NULL) { teleportDelay++;
int xn = Mth::floor(e->x * 32.0); int yn = Mth::floor(e->y * 32.0); int zn = Mth::floor(e->z * 32.0); int xa = xn - xp; int ya = yn - yp; int za = zn - zp;
shared_ptr<Packet> packet = nullptr;
// 4J - this pos flag used to be set based on abs(xn) etc. but that just seems wrong bool pos = abs(xa) >= TOLERANCE_LEVEL || abs(ya) >= TOLERANCE_LEVEL || abs(za) >= TOLERANCE_LEVEL || (tickCount % (SharedConstants::TICKS_PER_SECOND * 3) == 0);
// Keep rotation deltas in +/- 180 degree range while( yRota > 127 ) yRota -= 256; while( yRota < -128 ) yRota += 256; while( xRota > 127 ) xRota -= 256; while( xRota < -128 ) xRota += 256;
bool rot = abs(yRota) >= TOLERANCE_LEVEL || abs(xRota) >= TOLERANCE_LEVEL;
// 4J: Modified the following check. It was originally added by Mojang to address // certain unspecified issues with entity position. Turns out the issue effects a // variety of different entities so we've left it in and just added the new exceptions // (so far just players)
// 4J: Original comment follows // TODO: Figure out how to fix this properly // skip first tick since position is sent in addEntity packet // FallingTile depends on this because it removes its source block in the first tick()
if (tickCount > 0 || e->instanceof(eTYPE_ARROW) || e->instanceof(eTYPE_PLAYER)) // 4J: Modifed, see above { if (xa < -128 || xa >= 128 || ya < -128 || ya >= 128 || za < -128 || za >= 128 || wasRiding // 4J Stu - I fixed the initialisation of teleportDelay in the ctor, but we managed this far without out // and would prefer not to have all the extra traffix so ignore it // 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. || (e->GetType() == eTYPE_BOAT && teleportDelay > 20 * 20) ) { teleportDelay = 0; packet = shared_ptr<TeleportEntityPacket>( new TeleportEntityPacket(e->entityId, xn, yn, zn, (byte) yRotn, (byte) xRotn) ); // printf("%d: New teleport rot %d\n",e->entityId,yRotn); yRotp = yRotn; xRotp = xRotn; } else { if (pos && rot) { // 4J If the movement is small enough, and there's no xrot, then use the new smaller packets if( ( xa >= -16 ) && ( xa <= 15 ) && ( za >= -16 ) && ( za <= 15 ) && ( ya >= -32 ) && ( ya <= 31 ) && ( xRota == 0 )) { // Clamp rotations that are too big if( yRota < -16 ) { yRota = -16; yRotn = yRotp + yRota; } else if( yRota > 15 ) { yRota = 15; yRotn = yRotp + yRota; } // 5 bits each for x & z, and 6 for y packet = shared_ptr<MoveEntityPacketSmall>( new MoveEntityPacketSmall::PosRot(e->entityId, (char) xa, (char) ya, (char) za, (char) yRota, 0 ) ); c0a++; } else { packet = shared_ptr<MoveEntityPacket>( new MoveEntityPacket::PosRot(e->entityId, (char) xa, (char) ya, (char) za, (char) yRota, (char) xRota) ); // printf("%d: New posrot %d + %d = %d\n",e->entityId,yRotp,yRota,yRotn); c0b++; } } else if (pos) { // 4J If the movement is small enough, then use the new smaller packets if( ( xa >= -8 ) && ( xa <= 7 ) && ( za >= -8 ) && ( za <= 7 ) && ( ya >= -16 ) && ( ya <= 15 ) ) { // 4 bits each for x & z, and 5 for y packet = shared_ptr<MoveEntityPacketSmall>( new MoveEntityPacketSmall::Pos(e->entityId, (char) xa, (char) ya, (char) za) ); c1a++; }
else if( ( xa >= -16 ) && ( xa <= 15 ) && ( za >= -16 ) && ( za <= 15 ) && ( ya >= -32 ) && ( ya <= 31 ) ) { // 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 packet = shared_ptr<MoveEntityPacketSmall>( new MoveEntityPacketSmall::PosRot(e->entityId, (char) xa, (char) ya, (char) za, 0, 0 )); c1b++; } else { packet = shared_ptr<MoveEntityPacket>( new MoveEntityPacket::Pos(e->entityId, (char) xa, (char) ya, (char) za) ); c1c++; } } else if (rot) { // 4J If there's no x rotation, then use the new smaller packet type if( xRota == 0 ) { // Clamp rotations that are too big if( yRota < -16 ) { yRota = -16; yRotn = yRotp + yRota; } else if( yRota > 15 ) { yRota = 15; yRotn = yRotp + yRota; } packet = shared_ptr<MoveEntityPacketSmall>( new MoveEntityPacketSmall::Rot(e->entityId, (char) yRota, 0) ); c2a++; } else { // printf("%d: New rot %d + %d = %d\n",e->entityId,yRotp,yRota,yRotn); packet = shared_ptr<MoveEntityPacket>( new MoveEntityPacket::Rot(e->entityId, (char) yRota, (char) xRota) ); c2b++; } } } }
if (trackDelta) { double xad = e->xd - xap; double yad = e->yd - yap; double zad = e->zd - zap;
double max = 0.02;
double diff = xad * xad + yad * yad + zad * zad;
if (diff > max * max || (diff > 0 && e->xd == 0 && e->yd == 0 && e->zd == 0)) { xap = e->xd; yap = e->yd; zap = e->zd; broadcast( shared_ptr<SetEntityMotionPacket>( new SetEntityMotionPacket(e->entityId, xap, yap, zap) ) ); }
}
if (packet != NULL) { broadcast(packet); }
sendDirtyEntityData();
if (pos) { xp = xn; yp = yn; zp = zn; } if (rot) { yRotp = yRotn; xRotp = xRotn; }
wasRiding = false; } else { bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL; if (rot) { // 4J: Changed this to use deltas broadcast( shared_ptr<MoveEntityPacket>( new MoveEntityPacket::Rot(e->entityId, (byte) yRota, (byte) xRota)) ); yRotp = yRotn; xRotp = xRotn; } xp = Mth::floor(e->x * 32.0); yp = Mth::floor(e->y * 32.0); zp = Mth::floor(e->z * 32.0);
sendDirtyEntityData();
wasRiding = true; }
int yHeadRot = Mth::floor(e->getYHeadRot() * 256 / 360); if (abs(yHeadRot - yHeadRotp) >= TOLERANCE_LEVEL) { broadcast(shared_ptr<RotateHeadPacket>( new RotateHeadPacket(e->entityId, (byte) yHeadRot))); yHeadRotp = yHeadRot; }
e->hasImpulse = false; }
tickCount++;
if (e->hurtMarked) { // broadcast(new AnimatePacket(e, AnimatePacket.HURT)); broadcastAndSend( shared_ptr<SetEntityMotionPacket>( new SetEntityMotionPacket(e) ) ); e->hurtMarked = false; }
}
void TrackedEntity::sendDirtyEntityData(){ shared_ptr<SynchedEntityData> entityData = e->getEntityData(); if (entityData->isDirty()) { broadcastAndSend( shared_ptr<SetEntityDataPacket>( new SetEntityDataPacket(e->entityId, entityData, false)) ); }
if ( e->instanceof(eTYPE_LIVINGENTITY) ) { shared_ptr<LivingEntity> living = dynamic_pointer_cast<LivingEntity>(e); ServersideAttributeMap *attributeMap = (ServersideAttributeMap *) living->getAttributes(); unordered_set<AttributeInstance *> *attributes = attributeMap->getDirtyAttributes();
if (!attributes->empty()) { broadcastAndSend(shared_ptr<UpdateAttributesPacket>( new UpdateAttributesPacket(e->entityId, attributes)) ); }
attributes->clear(); }}
void TrackedEntity::broadcast(shared_ptr<Packet> packet){ if( Packet::canSendToAnyClient( packet ) ) { // 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 vector< shared_ptr<ServerPlayer> > sentTo;
// 4J - don't send to a player we've already sent this data to that shares the same machine. // EntityMotionPacket used to limit themselves to sending once to each machine // by only sending to the primary player on each machine. This was causing trouble for split screen // as only the primary player would get a knockback velocity. Now these packets can be sent to any // player, but we try to restrict the network impact this has by not resending to the one machine
for( AUTO_VAR(it, seenBy.begin()); it != seenBy.end(); it++ ) { shared_ptr<ServerPlayer> player = *it; bool dontSend = false; if( sentTo.size() ) { INetworkPlayer *thisPlayer =player->connection->getNetworkPlayer(); if( thisPlayer == NULL ) { dontSend = true; } else { for(unsigned int j = 0; j < sentTo.size(); j++ ) { shared_ptr<ServerPlayer> player2 = sentTo[j]; INetworkPlayer *otherPlayer = player2->connection->getNetworkPlayer(); if( otherPlayer != NULL && thisPlayer->IsSameSystem(otherPlayer) ) { dontSend = true; // #ifdef _DEBUG // shared_ptr<SetEntityMotionPacket> emp= dynamic_pointer_cast<SetEntityMotionPacket> (packet); // if(emp!=NULL) // { // app.DebugPrintf("Not sending this SetEntityMotionPacket to player - it's already been sent to a player on their console\n"); // } // #endif } } } } if( dontSend ) { continue; }
(*it)->connection->send(packet); sentTo.push_back(player); } } else { // This packet hasn't got canSendToAnyClient set, so just send to everyone here, and it
for( AUTO_VAR(it, seenBy.begin()); it != seenBy.end(); it++ ) { (*it)->connection->send(packet); } }}
void TrackedEntity::broadcastAndSend(shared_ptr<Packet> packet){ vector< shared_ptr<ServerPlayer> > sentTo; broadcast(packet); shared_ptr<ServerPlayer> sp = e->instanceof(eTYPE_SERVERPLAYER) ? dynamic_pointer_cast<ServerPlayer>(e) : nullptr; if (sp != NULL && sp->connection) { sp->connection->send(packet); }}
void TrackedEntity::broadcastRemoved(){ for( AUTO_VAR(it, seenBy.begin()); it != seenBy.end(); it++ ) { (*it)->entitiesToRemove.push_back(e->entityId); }}
void TrackedEntity::removePlayer(shared_ptr<ServerPlayer> sp){ AUTO_VAR(it, seenBy.find( sp )); if( it != seenBy.end() ) { sp->entitiesToRemove.push_back(e->entityId); seenBy.erase( it ); }}
// 4J-JEV: Added for code reuse.TrackedEntity::eVisibility TrackedEntity::isVisible(EntityTracker *tracker, shared_ptr<ServerPlayer> sp, bool forRider){ // 4J Stu - We call update players when the entity has moved more than a certain amount at the start of it's tick // 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. // Therefore we should use the new position for visibility checks double xd = sp->x - xpu; //xp / 32; double zd = sp->z - zpu; //zp / 32;
// 4J Stu - Fix for loading a player who is currently riding something (e.g. a horse) if(e->forcedLoading) { xd = sp->x - xp / 32; zd = sp->z - zp / 32; }
int playersRange = range; if( playersRange > TRACKED_ENTITY_MINIMUM_VIEW_DISTANCE ) { playersRange -= sp->getPlayerViewDistanceModifier(); }
bool bVisible = xd >= -playersRange && xd <= playersRange && zd >= -playersRange && zd <= playersRange; bool canBeSeenBy = canBySeenBy(sp);
// 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 // 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 // players who canReceiveAllPackets(). if(!bVisible) { MinecraftServer *server = MinecraftServer::getInstance(); INetworkPlayer *thisPlayer = sp->connection->getNetworkPlayer(); if( thisPlayer ) { for( unsigned int i = 0; i < server->getPlayers()->players.size(); i++ ) { // 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 shared_ptr<ServerPlayer> ep = server->getPlayers()->players[i]; if( ep == sp ) continue; if( ep == e ) continue; if( ep->dimension != sp->dimension ) continue;
INetworkPlayer * otherPlayer = ep->connection->getNetworkPlayer(); if( otherPlayer != NULL && thisPlayer->IsSameSystem(otherPlayer) ) { // 4J Stu - We call update players when the entity has moved more than a certain amount at the start of it's tick // 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. // Therefore we should use the new position for visibility checks double xd = ep->x - xpu; //xp / 32; double zd = ep->z - zpu; //zp / 32; bVisible |= ( xd >= -playersRange && xd <= playersRange && zd >= -playersRange && zd <= playersRange ); canBeSeenBy |= canBySeenBy(ep); } } } }
// 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 if(forRider) { canBeSeenBy = canBeSeenBy && (seenBy.find(sp) != seenBy.end()); }
// 4J-JEV: ADDED! An entities mount has to be visible before the entity visible, // this is to ensure that the mount is already in the client's game when the rider is added. if (canBeSeenBy && bVisible && e->riding != NULL) { return tracker->getTracker(e->riding)->isVisible(tracker, sp, true); } else if (canBeSeenBy && bVisible) return eVisibility_SeenAndVisible; else if (bVisible) return eVisibility_IsVisible; else return eVisibility_NotVisible;}
void TrackedEntity::updatePlayer(EntityTracker *tracker, shared_ptr<ServerPlayer> sp){ if (sp == e) return;
eVisibility visibility = this->isVisible(tracker, sp);
if ( visibility == eVisibility_SeenAndVisible && (seenBy.find(sp) == seenBy.end() || e->forcedLoading)) { seenBy.insert(sp); shared_ptr<Packet> packet = getAddEntityPacket(); sp->connection->send(packet);
xap = e->xd; yap = e->yd; zap = e->zd;
if ( e->instanceof(eTYPE_PLAYER) ) { shared_ptr<Player> plr = dynamic_pointer_cast<Player>(e); app.DebugPrintf( "TrackedEntity:: Player '%ls' is now visible to player '%ls', %s.\n", plr->name.c_str(), sp->name.c_str(), (e->riding==NULL?"not riding minecart":"in minecart") ); }
bool isAddMobPacket = dynamic_pointer_cast<AddMobPacket>(packet) != NULL;
// 4J Stu brought forward to fix when Item Frames if (!e->getEntityData()->isEmpty() && !isAddMobPacket) { sp->connection->send(shared_ptr<SetEntityDataPacket>( new SetEntityDataPacket(e->entityId, e->getEntityData(), true))); }
if ( e->instanceof(eTYPE_LIVINGENTITY) ) { shared_ptr<LivingEntity> living = dynamic_pointer_cast<LivingEntity>(e); ServersideAttributeMap *attributeMap = (ServersideAttributeMap *) living->getAttributes(); unordered_set<AttributeInstance *> *attributes = attributeMap->getSyncableAttributes();
if (!attributes->empty()) { sp->connection->send(shared_ptr<UpdateAttributesPacket>( new UpdateAttributesPacket(e->entityId, attributes)) ); } delete attributes; }
if (trackDelta && !isAddMobPacket) { sp->connection->send( shared_ptr<SetEntityMotionPacket>( new SetEntityMotionPacket(e->entityId, e->xd, e->yd, e->zd) ) ); }
if (e->riding != NULL) { sp->connection->send(shared_ptr<SetEntityLinkPacket>(new SetEntityLinkPacket(SetEntityLinkPacket::RIDING, e, e->riding))); } if ( e->instanceof(eTYPE_MOB) && dynamic_pointer_cast<Mob>(e)->getLeashHolder() != NULL) { sp->connection->send( shared_ptr<SetEntityLinkPacket>( new SetEntityLinkPacket(SetEntityLinkPacket::LEASH, e, dynamic_pointer_cast<Mob>(e)->getLeashHolder())) ); }
if ( e->instanceof(eTYPE_LIVINGENTITY) ) { for (int i = 0; i < 5; i++) { shared_ptr<ItemInstance> item = dynamic_pointer_cast<LivingEntity>(e)->getCarried(i); if(item != NULL) sp->connection->send( shared_ptr<SetEquippedItemPacket>( new SetEquippedItemPacket(e->entityId, i, item) ) ); } }
if ( e->instanceof(eTYPE_PLAYER) ) { shared_ptr<Player> spe = dynamic_pointer_cast<Player>(e); if (spe->isSleeping()) { sp->connection->send( shared_ptr<EntityActionAtPositionPacket>( new EntityActionAtPositionPacket(e, EntityActionAtPositionPacket::START_SLEEP, Mth::floor(e->x), Mth::floor(e->y), Mth::floor(e->z)) ) ); } }
if ( e->instanceof(eTYPE_LIVINGENTITY) ) { shared_ptr<LivingEntity> mob = dynamic_pointer_cast<LivingEntity>(e); vector<MobEffectInstance *> *activeEffects = mob->getActiveEffects(); for(AUTO_VAR(it, activeEffects->begin()); it != activeEffects->end(); ++it) { MobEffectInstance *effect = *it;
sp->connection->send(shared_ptr<UpdateMobEffectPacket>( new UpdateMobEffectPacket(e->entityId, effect) ) ); } delete activeEffects; } } else if (visibility == eVisibility_NotVisible) { AUTO_VAR(it, seenBy.find(sp)); if (it != seenBy.end()) { seenBy.erase(it); sp->entitiesToRemove.push_back(e->entityId); } }
}
bool TrackedEntity::canBySeenBy(shared_ptr<ServerPlayer> player){ // 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 // 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 // TODO - investigate further
return true; // return player->getLevel()->getChunkMap()->isPlayerIn(player, e->xChunk, e->zChunk);}
void TrackedEntity::updatePlayers(EntityTracker *tracker, vector<shared_ptr<Player> > *players){ for (unsigned int i = 0; i < players->size(); i++) { updatePlayer(tracker, dynamic_pointer_cast<ServerPlayer>( players->at(i) ) ); }}
shared_ptr<Packet> TrackedEntity::getAddEntityPacket(){ if (e->removed) { app.DebugPrintf("Fetching addPacket for removed entity - %ls\n", e->getAName().c_str()); }
// 4J-PB - replacing with a switch, rather than tons of ifs if (dynamic_pointer_cast<Creature>(e) != NULL) { yHeadRotp = Mth::floor(e->getYHeadRot() * 256 / 360); return shared_ptr<AddMobPacket>( new AddMobPacket(dynamic_pointer_cast<Mob>(e), yRotp, xRotp, xp, yp, zp, yHeadRotp) ); }
if (e->instanceof(eTYPE_ITEMENTITY)) { shared_ptr<AddEntityPacket> packet = shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::ITEM, 1, yRotp, xRotp, xp, yp, zp) ); return packet; } else if (e->instanceof(eTYPE_SERVERPLAYER)) { shared_ptr<ServerPlayer> player = dynamic_pointer_cast<ServerPlayer>(e);
PlayerUID xuid = INVALID_XUID; PlayerUID OnlineXuid = INVALID_XUID; if( player != NULL ) { xuid = player->getXuid(); OnlineXuid = player->getOnlineXuid(); } // 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. return shared_ptr<AddPlayerPacket>( new AddPlayerPacket( player, xuid, OnlineXuid, xp, yp, zp, yRotp, xRotp, yHeadRotp ) ); } else if (e->instanceof(eTYPE_MINECART)) { shared_ptr<Minecart> minecart = dynamic_pointer_cast<Minecart>(e); return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::MINECART, minecart->getType(), yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_BOAT)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::BOAT, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_ENDERDRAGON)) { yHeadRotp = Mth::floor(e->getYHeadRot() * 256 / 360); return shared_ptr<AddMobPacket>( new AddMobPacket(dynamic_pointer_cast<LivingEntity>(e), yRotp, xRotp, xp, yp, zp, yHeadRotp ) ); } else if (e->instanceof(eTYPE_FISHINGHOOK)) { shared_ptr<Entity> owner = dynamic_pointer_cast<FishingHook>(e)->owner; return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::FISH_HOOK, owner != NULL ? owner->entityId : e->entityId, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_ARROW)) { shared_ptr<Entity> owner = (dynamic_pointer_cast<Arrow>(e))->owner; return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::ARROW, owner != NULL ? owner->entityId : e->entityId, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_SNOWBALL)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::SNOWBALL, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_THROWNPOTION)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::THROWN_POTION, ((dynamic_pointer_cast<ThrownPotion>(e))->getPotionValue()), yRotp, xRotp, xp, yp, zp)); } else if (e->instanceof(eTYPE_THROWNEXPBOTTLE)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::THROWN_EXPBOTTLE, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_THROWNENDERPEARL)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::THROWN_ENDERPEARL, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_EYEOFENDERSIGNAL)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::EYEOFENDERSIGNAL, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_FIREWORKS_ROCKET)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::FIREWORKS, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_FIREBALL)) { eINSTANCEOF classType = e->GetType(); int type = AddEntityPacket::FIREBALL; if (classType == eTYPE_SMALL_FIREBALL) { type = AddEntityPacket::SMALL_FIREBALL; } else if (classType == eTYPE_DRAGON_FIREBALL) { type = AddEntityPacket::DRAGON_FIRE_BALL; } else if (classType == eTYPE_WITHER_SKULL) { type = AddEntityPacket::WITHER_SKULL; }
shared_ptr<Fireball> fb = dynamic_pointer_cast<Fireball>(e); shared_ptr<AddEntityPacket> aep = nullptr; if (fb->owner != NULL) { aep = shared_ptr<AddEntityPacket>( new AddEntityPacket(e, type, fb->owner->entityId, yRotp, xRotp, xp, yp, zp) ); } else { aep = shared_ptr<AddEntityPacket>( new AddEntityPacket(e, type, 0, yRotp, xRotp, xp, yp, zp) ); } aep->xa = (int) (fb->xPower * 8000); aep->ya = (int) (fb->yPower * 8000); aep->za = (int) (fb->zPower * 8000); return aep; } else if (e->instanceof(eTYPE_THROWNEGG)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::EGG, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_PRIMEDTNT)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::PRIMED_TNT, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_ENDER_CRYSTAL)) { return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::ENDER_CRYSTAL, yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_FALLINGTILE)) { shared_ptr<FallingTile> ft = dynamic_pointer_cast<FallingTile>(e); return shared_ptr<AddEntityPacket>( new AddEntityPacket(e, AddEntityPacket::FALLING, ft->tile | (ft->data << 16), yRotp, xRotp, xp, yp, zp) ); } else if (e->instanceof(eTYPE_PAINTING)) { return shared_ptr<AddPaintingPacket>( new AddPaintingPacket(dynamic_pointer_cast<Painting>(e)) ); } else if (e->instanceof(eTYPE_ITEM_FRAME)) { shared_ptr<ItemFrame> frame = dynamic_pointer_cast<ItemFrame>(e); {
int ix= (int)frame->xTile; int iy= (int)frame->yTile; int iz= (int)frame->zTile; app.DebugPrintf("eTYPE_ITEM_FRAME xyz %d,%d,%d\n",ix,iy,iz); }
shared_ptr<AddEntityPacket> packet = shared_ptr<AddEntityPacket>(new AddEntityPacket(e, AddEntityPacket::ITEM_FRAME, frame->dir, yRotp, xRotp, xp, yp, zp)); packet->x = Mth::floor(frame->xTile * 32.0f); packet->y = Mth::floor(frame->yTile * 32.0f); packet->z = Mth::floor(frame->zTile * 32.0f); return packet; } else if (e->instanceof(eTYPE_LEASHFENCEKNOT)) { shared_ptr<LeashFenceKnotEntity> knot = dynamic_pointer_cast<LeashFenceKnotEntity>(e); shared_ptr<AddEntityPacket> packet = shared_ptr<AddEntityPacket>(new AddEntityPacket(e, AddEntityPacket::LEASH_KNOT, yRotp, xRotp, xp, yp, zp) ); packet->x = Mth::floor((float)knot->xTile * 32); packet->y = Mth::floor((float)knot->yTile * 32); packet->z = Mth::floor((float)knot->zTile * 32); return packet; } else if (e->instanceof(eTYPE_EXPERIENCEORB)) { return shared_ptr<AddExperienceOrbPacket>( new AddExperienceOrbPacket(dynamic_pointer_cast<ExperienceOrb>(e)) ); } else { assert(false); }
return nullptr;}
void TrackedEntity::clear(shared_ptr<ServerPlayer> sp){ AUTO_VAR(it, seenBy.find(sp)); if (it != seenBy.end()) { seenBy.erase(it); sp->entitiesToRemove.push_back(e->entityId); }}