From b3feddfef372618c8a9d7a0abcaf18cfad866c18 Mon Sep 17 00:00:00 2001 From: daoge <3523206925@qq.com> Date: Tue, 3 Mar 2026 03:04:10 +0800 Subject: feat: TU19 (Dec 2014) Features & Content (#155) * try to resolve merge conflict * feat: TU19 (Dec 2014) Features & Content (#32) * December 2014 files * Working release build * Fix compilation issues * Add sound to Windows64Media * Add DLC content and force Tutorial DLC * Revert "Add DLC content and force Tutorial DLC" This reverts commit 97a43994725008e35fceb984d5549df9c8cea470. * Disable broken light packing * Disable breakpoint during DLC texture map load Allows DLC loading but the DLC textures are still broken * Fix post build not working * ... * fix vs2022 build * fix cmake build --------- Co-authored-by: Loki --- Minecraft.Client/ClientConnection.cpp | 1413 +++++++++++++++++++++++---------- 1 file changed, 976 insertions(+), 437 deletions(-) (limited to 'Minecraft.Client/ClientConnection.cpp') diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index 5ba3cb85..52cec351 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -13,7 +13,9 @@ #include "..\Minecraft.World\net.minecraft.world.level.chunk.h" #include "..\Minecraft.World\net.minecraft.stats.h" #include "..\Minecraft.World\net.minecraft.world.entity.h" +#include "..\Minecraft.World\net.minecraft.world.entity.ai.attributes.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.npc.h" #include "..\Minecraft.World\net.minecraft.world.entity.item.h" #include "..\Minecraft.World\net.minecraft.world.entity.projectile.h" @@ -41,6 +43,7 @@ #include "MinecraftServer.h" #include "ClientConstants.h" #include "..\Minecraft.World\SoundTypes.h" +#include "..\Minecraft.World\BasicTypeContainers.h" #include "TexturePackRepository.h" #ifdef _XBOX #include "Common\XUI\XUI_Scene_Trading.h" @@ -65,15 +68,15 @@ ClientConnection::ClientConnection(Minecraft *minecraft, const wstring& ip, int // 4J - added initiliasers random = new Random(); done = false; - level = false; - started = false; + level = false; + started = false; - this->minecraft = minecraft; + this->minecraft = minecraft; Socket *socket; if( gNetworkManager.IsHost() ) { - socket = new Socket(); // 4J - Local connection + socket = new Socket(); // 4J - Local connection } else { @@ -82,7 +85,7 @@ ClientConnection::ClientConnection(Minecraft *minecraft, const wstring& ip, int createdOk = socket->createdOk; if( createdOk ) { - connection = new Connection(socket, L"Client", this); + connection = new Connection(socket, L"Client", this); } else { @@ -97,12 +100,12 @@ ClientConnection::ClientConnection(Minecraft *minecraft, Socket *socket, int iUs // 4J - added initiliasers random = new Random(); done = false; - level = NULL; - started = false; + level = NULL; + started = false; savedDataStorage = new SavedDataStorage(NULL); maxPlayers = 20; - this->minecraft = minecraft; + this->minecraft = minecraft; if( iUserIndex < 0 ) { @@ -115,13 +118,13 @@ ClientConnection::ClientConnection(Minecraft *minecraft, Socket *socket, int iUs if( socket == NULL ) { - socket = new Socket(); // 4J - Local connection + socket = new Socket(); // 4J - Local connection } createdOk = socket->createdOk; if( createdOk ) { - connection = new Connection(socket, L"Client", this); + connection = new Connection(socket, L"Client", this); } else { @@ -129,6 +132,8 @@ ClientConnection::ClientConnection(Minecraft *minecraft, Socket *socket, int iUs // TODO 4J Stu - This will cause issues since the session player owns the socket //delete socket; } + + deferredEntityLinkPackets = vector(); } ClientConnection::~ClientConnection() @@ -140,8 +145,8 @@ ClientConnection::~ClientConnection() void ClientConnection::tick() { - if (!done) connection->tick(); - connection->flush(); + if (!done) connection->tick(); + connection->flush(); } INetworkPlayer *ClientConnection::getNetworkPlayer() @@ -152,7 +157,7 @@ INetworkPlayer *ClientConnection::getNetworkPlayer() void ClientConnection::handleLogin(shared_ptr packet) { - if (done) return; + if (done) return; PlayerUID OnlineXuid; ProfileManager.GetXUID(m_userIndex,&OnlineXuid,true); // online xuid @@ -405,26 +410,18 @@ void ClientConnection::handleLogin(shared_ptr packet) void ClientConnection::handleAddEntity(shared_ptr packet) { - double x = packet->x / 32.0; - double y = packet->y / 32.0; - double z = packet->z / 32.0; - shared_ptr e; - boolean setRot = true; + double x = packet->x / 32.0; + double y = packet->y / 32.0; + double z = packet->z / 32.0; + shared_ptr e; + bool setRot = true; // 4J-PB - replacing this massive if nest with switch switch(packet->type) { - case AddEntityPacket::MINECART_RIDEABLE: - e = shared_ptr( new Minecart(level, x, y, z, Minecart::RIDEABLE) ); - break; - case AddEntityPacket::MINECART_CHEST: - e = shared_ptr( new Minecart(level, x, y, z, Minecart::CHEST) ); - break; - - case AddEntityPacket::MINECART_FURNACE: - e = shared_ptr( new Minecart(level, x, y, z, Minecart::FURNACE) ); + case AddEntityPacket::MINECART: + e = Minecart::createMinecart(level, x, y, z, packet->data); break; - case AddEntityPacket::FISH_HOOK: { // 4J Stu - Brought forward from 1.4 to be able to drop XP from fishing @@ -446,9 +443,10 @@ void ClientConnection::handleAddEntity(shared_ptr packet) } } } - shared_ptr player = dynamic_pointer_cast(owner); - if (player != NULL) + + if (owner->instanceof(eTYPE_PLAYER)) { + shared_ptr player = dynamic_pointer_cast(owner); shared_ptr hook = shared_ptr( new FishingHook(level, x, y, z, player) ); e = hook; // 4J Stu - Move the player->fishing out of the ctor as we cannot reference 'this' @@ -463,17 +461,17 @@ void ClientConnection::handleAddEntity(shared_ptr packet) case AddEntityPacket::SNOWBALL: e = shared_ptr( new Snowball(level, x, y, z) ); break; - case AddEntityPacket::ITEM_FRAME: + case AddEntityPacket::ITEM_FRAME: { int ix=(int) x; int iy=(int) y; int iz = (int) z; app.DebugPrintf("ClientConnection ITEM_FRAME xyz %d,%d,%d\n",ix,iy,iz); } - e = shared_ptr(new ItemFrame(level, (int) x, (int) y, (int) z, packet->data)); - packet->data = 0; - setRot = false; - break; + e = shared_ptr(new ItemFrame(level, (int) x, (int) y, (int) z, packet->data)); + packet->data = 0; + setRot = false; + break; case AddEntityPacket::THROWN_ENDERPEARL: e = shared_ptr( new ThrownEnderpearl(level, x, y, z) ); break; @@ -481,7 +479,7 @@ void ClientConnection::handleAddEntity(shared_ptr packet) e = shared_ptr( new EyeOfEnderSignal(level, x, y, z) ); break; case AddEntityPacket::FIREBALL: - e = shared_ptr( new Fireball(level, x, y, z, packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0) ); + e = shared_ptr( new LargeFireball(level, x, y, z, packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0) ); packet->data = 0; break; case AddEntityPacket::SMALL_FIREBALL: @@ -507,7 +505,7 @@ void ClientConnection::handleAddEntity(shared_ptr packet) e = shared_ptr( new Boat(level, x, y, z) ); break; case AddEntityPacket::PRIMED_TNT: - e = shared_ptr( new PrimedTnt(level, x, y, z) ); + e = shared_ptr( new PrimedTnt(level, x, y, z, nullptr) ); break; case AddEntityPacket::ENDER_CRYSTAL: e = shared_ptr( new EnderCrystal(level, x, y, z) ); @@ -519,14 +517,28 @@ void ClientConnection::handleAddEntity(shared_ptr packet) e = shared_ptr( new FallingTile(level, x, y, z, packet->data & 0xFFFF, packet->data >> 16) ); packet->data = 0; break; - - - + case AddEntityPacket::WITHER_SKULL: + e = shared_ptr(new WitherSkull(level, x, y, z, packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0)); + packet->data = 0; + break; + case AddEntityPacket::FIREWORKS: + e = shared_ptr(new FireworksRocketEntity(level, x, y, z, nullptr)); + break; + case AddEntityPacket::LEASH_KNOT: + e = shared_ptr(new LeashFenceKnotEntity(level, (int) x, (int) y, (int) z)); + packet->data = 0; + break; +#ifndef _FINAL_BUILD + default: + // Not a known entity (?) + assert(0); +#endif } + /* if (packet->type == AddEntityPacket::MINECART_RIDEABLE) e = shared_ptr( new Minecart(level, x, y, z, Minecart::RIDEABLE) ); - if (packet->type == AddEntityPacket::MINECART_CHEST) e = shared_ptr( new Minecart(level, x, y, z, Minecart::CHEST) ); - if (packet->type == AddEntityPacket::MINECART_FURNACE) e = shared_ptr( new Minecart(level, x, y, z, Minecart::FURNACE) ); - if (packet->type == AddEntityPacket::FISH_HOOK) + if (packet->type == AddEntityPacket::MINECART_CHEST) e = shared_ptr( new Minecart(level, x, y, z, Minecart::CHEST) ); + if (packet->type == AddEntityPacket::MINECART_FURNACE) e = shared_ptr( new Minecart(level, x, y, z, Minecart::FURNACE) ); + if (packet->type == AddEntityPacket::FISH_HOOK) { // 4J Stu - Brought forward from 1.4 to be able to drop XP from fishing shared_ptr owner = getEntity(packet->data); @@ -558,21 +570,21 @@ void ClientConnection::handleAddEntity(shared_ptr packet) packet->data = 0; } - if (packet->type == AddEntityPacket::ARROW) e = shared_ptr( new Arrow(level, x, y, z) ); - if (packet->type == AddEntityPacket::SNOWBALL) e = shared_ptr( new Snowball(level, x, y, z) ); + if (packet->type == AddEntityPacket::ARROW) e = shared_ptr( new Arrow(level, x, y, z) ); + if (packet->type == AddEntityPacket::SNOWBALL) e = shared_ptr( new Snowball(level, x, y, z) ); if (packet->type == AddEntityPacket::THROWN_ENDERPEARL) e = shared_ptr( new ThrownEnderpearl(level, x, y, z) ); if (packet->type == AddEntityPacket::EYEOFENDERSIGNAL) e = shared_ptr( new EyeOfEnderSignal(level, x, y, z) ); - if (packet->type == AddEntityPacket::FIREBALL) + if (packet->type == AddEntityPacket::FIREBALL) { - e = shared_ptr( new Fireball(level, x, y, z, packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0) ); - packet->data = 0; - } + e = shared_ptr( new Fireball(level, x, y, z, packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0) ); + packet->data = 0; + } if (packet->type == AddEntityPacket::SMALL_FIREBALL) { e = shared_ptr( new SmallFireball(level, x, y, z, packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0) ); packet->data = 0; } - if (packet->type == AddEntityPacket::EGG) e = shared_ptr( new ThrownEgg(level, x, y, z) ); + if (packet->type == AddEntityPacket::EGG) e = shared_ptr( new ThrownEgg(level, x, y, z) ); if (packet->type == AddEntityPacket::THROWN_POTION) { e = shared_ptr( new ThrownPotion(level, x, y, z, packet->data) ); @@ -583,20 +595,20 @@ void ClientConnection::handleAddEntity(shared_ptr packet) e = shared_ptr( new ThrownExpBottle(level, x, y, z) ); packet->data = 0; } - if (packet->type == AddEntityPacket::BOAT) e = shared_ptr( new Boat(level, x, y, z) ); - if (packet->type == AddEntityPacket::PRIMED_TNT) e = shared_ptr( new PrimedTnt(level, x, y, z) ); + if (packet->type == AddEntityPacket::BOAT) e = shared_ptr( new Boat(level, x, y, z) ); + if (packet->type == AddEntityPacket::PRIMED_TNT) e = shared_ptr( new PrimedTnt(level, x, y, z) ); if (packet->type == AddEntityPacket::ENDER_CRYSTAL) e = shared_ptr( new EnderCrystal(level, x, y, z) ); - if (packet->type == AddEntityPacket::FALLING_SAND) e = shared_ptr( new FallingTile(level, x, y, z, Tile::sand->id) ); - if (packet->type == AddEntityPacket::FALLING_GRAVEL) e = shared_ptr( new FallingTile(level, x, y, z, Tile::gravel->id) ); + if (packet->type == AddEntityPacket::FALLING_SAND) e = shared_ptr( new FallingTile(level, x, y, z, Tile::sand->id) ); + if (packet->type == AddEntityPacket::FALLING_GRAVEL) e = shared_ptr( new FallingTile(level, x, y, z, Tile::gravel->id) ); if (packet->type == AddEntityPacket::FALLING_EGG) e = shared_ptr( new FallingTile(level, x, y, z, Tile::dragonEgg_Id) ); */ - if (e != NULL) + if (e != NULL) { - e->xp = packet->x; - e->yp = packet->y; - e->zp = packet->z; + e->xp = packet->x; + e->yp = packet->y; + e->zp = packet->z; float yRot = packet->yRot * 360 / 256.0f; float xRot = packet->xRot * 360 / 256.0f; @@ -622,20 +634,29 @@ void ClientConnection::handleAddEntity(shared_ptr packet) } } - // Note - not doing this move for frame, as the ctor for these objects does some adjustments on the position based on direction to move the object out slightly from what it is attached to, and this just overwrites it - if( packet->type != AddEntityPacket::ITEM_FRAME ) + if (packet->type == AddEntityPacket::LEASH_KNOT) + { + // 4J: "Move" leash knot to it's current position, this sets old position (like frame, leash has adjusted position) + e->absMoveTo(e->x, e->y, e->z, yRot, xRot); + } + else if(packet->type == AddEntityPacket::ITEM_FRAME) + { + // Not doing this move for frame, as the ctor for these objects does some adjustments on the position based on direction to move the object out slightly from what it is attached to, and this just overwrites it + } + else { - e->absMoveTo(x,y,z,yRot,xRot); + // For everything else, set position + e->absMoveTo(x, y, z, yRot, xRot); } - e->entityId = packet->id; - level->putEntity(packet->id, e); + e->entityId = packet->id; + level->putEntity(packet->id, e); - if (packet->data > -1) // 4J - changed "no data" value to be -1, we can have a valid entity id of 0 + if (packet->data > -1) // 4J - changed "no data" value to be -1, we can have a valid entity id of 0 { - if (packet->type == AddEntityPacket::ARROW) + if (packet->type == AddEntityPacket::ARROW) { - shared_ptr owner = getEntity(packet->data); + shared_ptr owner = getEntity(packet->data); // 4J - check all local players to find match if( owner == NULL ) @@ -653,16 +674,18 @@ void ClientConnection::handleAddEntity(shared_ptr packet) } } - if (dynamic_pointer_cast(owner) != NULL) + if ( owner != NULL && owner->instanceof(eTYPE_LIVINGENTITY) ) { - dynamic_pointer_cast(e)->owner = dynamic_pointer_cast(owner); - } - } + dynamic_pointer_cast(e)->owner = dynamic_pointer_cast(owner); + } + } - e->lerpMotion(packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0); - } - } + e->lerpMotion(packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0); + } + // 4J: Check our deferred entity link packets + checkDeferredEntityLinkPackets(e->entityId); + } } void ClientConnection::handleAddExperienceOrb(shared_ptr packet) @@ -679,43 +702,43 @@ void ClientConnection::handleAddExperienceOrb(shared_ptr void ClientConnection::handleAddGlobalEntity(shared_ptr packet) { - double x = packet->x / 32.0; - double y = packet->y / 32.0; - double z = packet->z / 32.0; - shared_ptr e;// = nullptr; - if (packet->type == AddGlobalEntityPacket::LIGHTNING) e = shared_ptr( new LightningBolt(level, x, y, z) ); - if (e != NULL) + double x = packet->x / 32.0; + double y = packet->y / 32.0; + double z = packet->z / 32.0; + shared_ptr e;// = nullptr; + if (packet->type == AddGlobalEntityPacket::LIGHTNING) e = shared_ptr( new LightningBolt(level, x, y, z) ); + if (e != NULL) { - e->xp = packet->x; - e->yp = packet->y; - e->zp = packet->z; - e->yRot = 0; - e->xRot = 0; - e->entityId = packet->id; - level->addGlobalEntity(e); - } + e->xp = packet->x; + e->yp = packet->y; + e->zp = packet->z; + e->yRot = 0; + e->xRot = 0; + e->entityId = packet->id; + level->addGlobalEntity(e); + } } void ClientConnection::handleAddPainting(shared_ptr packet) { - shared_ptr painting = shared_ptr( new Painting(level, packet->x, packet->y, packet->z, packet->dir, packet->motive) ); - level->putEntity(packet->id, painting); + shared_ptr painting = shared_ptr( new Painting(level, packet->x, packet->y, packet->z, packet->dir, packet->motive) ); + level->putEntity(packet->id, painting); } void ClientConnection::handleSetEntityMotion(shared_ptr packet) { - shared_ptr e = getEntity(packet->id); - if (e == NULL) return; - e->lerpMotion(packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0); + shared_ptr e = getEntity(packet->id); + if (e == NULL) return; + e->lerpMotion(packet->xa / 8000.0, packet->ya / 8000.0, packet->za / 8000.0); } void ClientConnection::handleSetEntityData(shared_ptr packet) { - shared_ptr e = getEntity(packet->id); - if (e != NULL && packet->getUnpackedData() != NULL) + shared_ptr e = getEntity(packet->id); + if (e != NULL && packet->getUnpackedData() != NULL) { - e->getEntityData()->assignValues(packet->getUnpackedData()); - } + e->getEntityData()->assignValues(packet->getUnpackedData()); + } } void ClientConnection::handleAddPlayer(shared_ptr packet) @@ -750,15 +773,15 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) } #endif - double x = packet->x / 32.0; - double y = packet->y / 32.0; - double z = packet->z / 32.0; - float yRot = packet->yRot * 360 / 256.0f; - float xRot = packet->xRot * 360 / 256.0f; - shared_ptr player = shared_ptr( new RemotePlayer(minecraft->level, packet->name) ); - player->xo = player->xOld = player->xp = packet->x; - player->yo = player->yOld = player->yp = packet->y; - player->zo = player->zOld = player->zp = packet->z; + double x = packet->x / 32.0; + double y = packet->y / 32.0; + double z = packet->z / 32.0; + float yRot = packet->yRot * 360 / 256.0f; + float xRot = packet->xRot * 360 / 256.0f; + shared_ptr player = shared_ptr( new RemotePlayer(minecraft->level, packet->name) ); + player->xo = player->xOld = player->xp = packet->x; + player->yo = player->yOld = player->yp = packet->y; + player->zo = player->zOld = player->zp = packet->z; player->xRotp = packet->xRot; player->yRotp = packet->yRot; player->yHeadRot = packet->yHeadRot * 360 / 256.0f; @@ -767,24 +790,24 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) #ifdef _DURANGO // On Durango request player display name from network manager INetworkPlayer *networkPlayer = g_NetworkManager.GetPlayerByXuid(player->getXuid()); - if (networkPlayer != NULL) player->displayName = networkPlayer->GetDisplayName(); + if (networkPlayer != NULL) player->m_displayName = networkPlayer->GetDisplayName(); #else // On all other platforms display name is just gamertag so don't check with the network manager - player->displayName = player->name; + player->m_displayName = player->name; #endif // printf("\t\t\t\t%d: Add player\n",packet->id,packet->yRot); - int item = packet->carriedItem; - if (item == 0) + int item = packet->carriedItem; + if (item == 0) { - player->inventory->items[player->inventory->selected] = shared_ptr(); // NULL; - } + player->inventory->items[player->inventory->selected] = shared_ptr(); // NULL; + } else { - player->inventory->items[player->inventory->selected] = shared_ptr( new ItemInstance(item, 1, 0) ); - } - player->absMoveTo(x, y, z, yRot, xRot); + player->inventory->items[player->inventory->selected] = shared_ptr( new ItemInstance(item, 1, 0) ); + } + player->absMoveTo(x, y, z, yRot, xRot); player->setPlayerIndex( packet->m_playerIndex ); player->setCustomSkin( packet->m_skinId ); @@ -824,7 +847,7 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) app.DebugPrintf("Custom cape for player %ls is %ls\n",player->name.c_str(),player->customTextureUrl2.c_str()); - level->putEntity(packet->id, player); + level->putEntity(packet->id, player); vector > *unpackedData = packet->getUnpackedData(); if (unpackedData != NULL) @@ -836,37 +859,44 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) void ClientConnection::handleTeleportEntity(shared_ptr packet) { - shared_ptr e = getEntity(packet->id); - if (e == NULL) return; - e->xp = packet->x; - e->yp = packet->y; - e->zp = packet->z; - double x = e->xp / 32.0; - double y = e->yp / 32.0 + 1 / 64.0f; - double z = e->zp / 32.0; + shared_ptr e = getEntity(packet->id); + if (e == NULL) return; + e->xp = packet->x; + e->yp = packet->y; + e->zp = packet->z; + double x = e->xp / 32.0; + double y = e->yp / 32.0 + 1 / 64.0f; + double z = e->zp / 32.0; // 4J - make sure xRot stays within -90 -> 90 range int ixRot = packet->xRot; if( ixRot >= 128 ) ixRot -= 256; - float yRot = packet->yRot * 360 / 256.0f; - float xRot = ixRot * 360 / 256.0f; + float yRot = packet->yRot * 360 / 256.0f; + float xRot = ixRot * 360 / 256.0f; e->yRotp = packet->yRot; e->xRotp = ixRot; // printf("\t\t\t\t%d: Teleport to %d (lerp to %f)\n",packet->id,packet->yRot,yRot); - e->lerpTo(x, y, z, yRot, xRot, 3); + e->lerpTo(x, y, z, yRot, xRot, 3); +} + +void ClientConnection::handleSetCarriedItem(shared_ptr packet) +{ + if (packet->slot >= 0 && packet->slot < Inventory::getSelectionSize()) { + Minecraft::GetInstance()->localplayers[m_userIndex].get()->inventory->selected = packet->slot; + } } void ClientConnection::handleMoveEntity(shared_ptr packet) { - shared_ptr e = getEntity(packet->id); - if (e == NULL) return; - e->xp += packet->xa; - e->yp += packet->ya; - e->zp += packet->za; - double x = e->xp / 32.0; + shared_ptr e = getEntity(packet->id); + if (e == NULL) return; + e->xp += packet->xa; + e->yp += packet->ya; + e->zp += packet->za; + double x = e->xp / 32.0; // 4J - The original code did not add the 1/64.0f like the teleport above did, which caused minecarts to fall through the ground - double y = e->yp / 32.0 + 1 / 64.0f; - double z = e->zp / 32.0; + double y = e->yp / 32.0 + 1 / 64.0f; + double z = e->zp / 32.0; // 4J - have changed rotation to be relative here too e->yRotp += packet->yRot; e->xRotp += packet->xRot; @@ -874,7 +904,7 @@ void ClientConnection::handleMoveEntity(shared_ptr packet) float xRot = ( e->xRotp * 360 ) / 256.0f; // float yRot = packet->hasRot ? packet->yRot * 360 / 256.0f : e->yRot; // float xRot = packet->hasRot ? packet->xRot * 360 / 256.0f : e->xRot; - e->lerpTo(x, y, z, yRot, xRot, 3); + e->lerpTo(x, y, z, yRot, xRot, 3); } void ClientConnection::handleRotateMob(shared_ptr packet) @@ -887,15 +917,15 @@ void ClientConnection::handleRotateMob(shared_ptr packet) void ClientConnection::handleMoveEntitySmall(shared_ptr packet) { - shared_ptr e = getEntity(packet->id); - if (e == NULL) return; - e->xp += packet->xa; - e->yp += packet->ya; - e->zp += packet->za; - double x = e->xp / 32.0; + shared_ptr e = getEntity(packet->id); + if (e == NULL) return; + e->xp += packet->xa; + e->yp += packet->ya; + e->zp += packet->za; + double x = e->xp / 32.0; // 4J - The original code did not add the 1/64.0f like the teleport above did, which caused minecarts to fall through the ground - double y = e->yp / 32.0 + 1 / 64.0f; - double z = e->zp / 32.0; + double y = e->yp / 32.0 + 1 / 64.0f; + double z = e->zp / 32.0; // 4J - have changed rotation to be relative here too e->yRotp += packet->yRot; e->xRotp += packet->xRot; @@ -903,7 +933,7 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr p float xRot = ( e->xRotp * 360 ) / 256.0f; // float yRot = packet->hasRot ? packet->yRot * 360 / 256.0f : e->yRot; // float xRot = packet->hasRot ? packet->xRot * 360 / 256.0f : e->xRot; - e->lerpTo(x, y, z, yRot, xRot, 3); + e->lerpTo(x, y, z, yRot, xRot, 3); } void ClientConnection::handleRemoveEntity(shared_ptr packet) @@ -916,51 +946,51 @@ void ClientConnection::handleRemoveEntity(shared_ptr packe void ClientConnection::handleMovePlayer(shared_ptr packet) { - shared_ptr player = minecraft->localplayers[m_userIndex]; //minecraft->player; - - double x = player->x; - double y = player->y; - double z = player->z; - float yRot = player->yRot; - float xRot = player->xRot; - - if (packet->hasPos) - { - x = packet->x; - y = packet->y; - z = packet->z; - } - if (packet->hasRot) - { - yRot = packet->yRot; - xRot = packet->xRot; - } - - player->ySlideOffset = 0; - player->xd = player->yd = player->zd = 0; - player->absMoveTo(x, y, z, yRot, xRot); - packet->x = player->x; - packet->y = player->bb->y0; - packet->z = player->z; - packet->yView = player->y; - connection->send(packet); - if (!started) + shared_ptr player = minecraft->localplayers[m_userIndex]; //minecraft->player; + + double x = player->x; + double y = player->y; + double z = player->z; + float yRot = player->yRot; + float xRot = player->xRot; + + if (packet->hasPos) + { + x = packet->x; + y = packet->y; + z = packet->z; + } + if (packet->hasRot) + { + yRot = packet->yRot; + xRot = packet->xRot; + } + + player->ySlideOffset = 0; + player->xd = player->yd = player->zd = 0; + player->absMoveTo(x, y, z, yRot, xRot); + packet->x = player->x; + packet->y = player->bb->y0; + packet->z = player->z; + packet->yView = player->y; + connection->send(packet); + if (!started) { if(!g_NetworkManager.IsHost() ) { Minecraft::GetInstance()->progressRenderer->progressStagePercentage((eCCConnected * 100)/ (eCCConnected)); } - player->xo = player->x; - player->yo = player->y; - player->zo = player->z; + player->xo = player->x; + player->yo = player->y; + player->zo = player->z; // 4J - added setting xOld/yOld/zOld here too, as otherwise at the start of the game we interpolate the player position from the origin to wherever its first position really is player->xOld = player->x; player->yOld = player->y; player->zOld = player->z; - started = true; - minecraft->setScreen(NULL); + started = true; + minecraft->setScreen(NULL); // Fix for #105852 - TU12: Content: Gameplay: Local splitscreen Players are spawned at incorrect places after re-joining previously saved and loaded "Mass Effect World". // Move this check from Minecraft::createExtraLocalPlayer @@ -969,7 +999,7 @@ void ClientConnection::handleMovePlayer(shared_ptr packet) { ui.CloseUIScenes(m_userIndex); } - } + } } @@ -1067,24 +1097,37 @@ void ClientConnection::handleBlockRegionUpdate(shared_ptrbIsFullChunk) { y1 = Level::maxBuildHeight; - if(packet->buffer.length > 0) LevelChunk::reorderBlocksAndDataToXZY(packet->y, packet->xs, packet->ys, packet->zs, &packet->buffer); + if(packet->buffer.length > 0) + { + PIXBeginNamedEvent(0, "Reordering to XZY"); + LevelChunk::reorderBlocksAndDataToXZY(packet->y, packet->xs, packet->ys, packet->zs, &packet->buffer); + PIXEndNamedEvent(); + } } + PIXBeginNamedEvent(0,"Clear rest region"); dimensionLevel->clearResetRegion(packet->x, packet->y, packet->z, packet->x + packet->xs - 1, y1 - 1, packet->z + packet->zs - 1); + PIXEndNamedEvent(); + PIXBeginNamedEvent(0,"setBlocksAndData"); // Only full chunks send lighting information now - added flag to end of this call dimensionLevel->setBlocksAndData(packet->x, packet->y, packet->z, packet->xs, packet->ys, packet->zs, packet->buffer, packet->bIsFullChunk); + PIXEndNamedEvent(); // OutputDebugString("END BRU\n"); + PIXBeginNamedEvent(0,"removeUnusedTileEntitiesInRegion"); // 4J - remove any tite entities in this region which are associated with a tile that is now no longer a tile entity. Without doing this we end up with stray // tile entities kicking round, which leads to a bug where chests can't be properly placed again in a location after (say) a chest being removed by TNT dimensionLevel->removeUnusedTileEntitiesInRegion(packet->x, packet->y, packet->z, packet->x + packet->xs, y1, packet->z + packet->zs ); + PIXEndNamedEvent(); // If this is a full packet for a chunk, make sure that the cache now considers that it has data for this chunk - this is used to determine whether to bother // rendering mobs or not, so we don't have them in crazy positions before the data is there if( packet->bIsFullChunk ) { + PIXBeginNamedEvent(0,"dateReceivedForChunk"); dimensionLevel->dataReceivedForChunk( packet->x >> 4, packet->z >> 4 ); + PIXEndNamedEvent(); } PIXEndNamedEvent(); } @@ -1150,22 +1193,22 @@ void ClientConnection::handleTileUpdate(shared_ptr packet) void ClientConnection::handleDisconnect(shared_ptr packet) { connection->close(DisconnectPacket::eDisconnect_Kicked); - done = true; + done = true; Minecraft *pMinecraft = Minecraft::GetInstance(); pMinecraft->connectionDisconnected( m_userIndex , packet->reason ); app.SetDisconnectReason( packet->reason ); app.SetAction(m_userIndex,eAppAction_ExitWorld,(void *)TRUE); - //minecraft->setLevel(NULL); + //minecraft->setLevel(NULL); //minecraft->setScreen(new DisconnectedScreen(L"disconnect.disconnected", L"disconnect.genericReason", &packet->reason)); } void ClientConnection::onDisconnect(DisconnectPacket::eDisconnectReason reason, void *reasonObjects) { - if (done) return; - done = true; + if (done) return; + done = true; Minecraft *pMinecraft = Minecraft::GetInstance(); pMinecraft->connectionDisconnected( m_userIndex , reason ); @@ -1180,34 +1223,34 @@ void ClientConnection::onDisconnect(DisconnectPacket::eDisconnectReason reason, { UINT uiIDA[1]; uiIDA[0]=IDS_CONFIRM_OK; - ui.RequestMessageBox(IDS_EXITING_GAME, IDS_GENERIC_ERROR, uiIDA, 1, ProfileManager.GetPrimaryPad(),&ClientConnection::HostDisconnectReturned,NULL, app.GetStringTable()); + ui.RequestErrorMessage(IDS_EXITING_GAME, IDS_GENERIC_ERROR, uiIDA, 1, ProfileManager.GetPrimaryPad(),&ClientConnection::HostDisconnectReturned,NULL); } else { app.SetAction(m_userIndex,eAppAction_ExitWorld,(void *)TRUE); } - //minecraft->setLevel(NULL); - //minecraft->setScreen(new DisconnectedScreen(L"disconnect.lost", reason, reasonObjects)); + //minecraft->setLevel(NULL); + //minecraft->setScreen(new DisconnectedScreen(L"disconnect.lost", reason, reasonObjects)); } void ClientConnection::sendAndDisconnect(shared_ptr packet) { - if (done) return; - connection->send(packet); - connection->sendAndQuit(); + if (done) return; + connection->send(packet); + connection->sendAndQuit(); } void ClientConnection::send(shared_ptr packet) { - if (done) return; - connection->send(packet); + if (done) return; + connection->send(packet); } void ClientConnection::handleTakeItemEntity(shared_ptr packet) { - shared_ptr from = getEntity(packet->itemId); - shared_ptr to = dynamic_pointer_cast(getEntity(packet->playerId)); + shared_ptr from = getEntity(packet->itemId); + shared_ptr to = dynamic_pointer_cast(getEntity(packet->playerId)); // 4J - the original game could assume that if getEntity didn't find the player, it must be the local player. We // need to search all local players @@ -1225,15 +1268,15 @@ void ClientConnection::handleTakeItemEntity(shared_ptr pac } } - if (to == NULL) + if (to == NULL) { // Don't know if this should ever really happen, but seems safest to try and remove the entity that has been collected even if we can't // create a particle as we don't know what really collected it level->removeEntity(packet->itemId); - return; - } + return; + } - if (from != NULL) + if (from != NULL) { // If this is a local player, then we only want to do processing for it if this connection is associated with the player it is for. In // particular, we don't want to remove the item entity until we are processing it for the right connection, or else we won't have a valid @@ -1277,7 +1320,7 @@ void ClientConnection::handleTakeItemEntity(shared_ptr pac minecraft->particleEngine->add( shared_ptr( new TakeAnimationParticle(minecraft->level, from, to, -0.5f) ) ); level->removeEntity(packet->itemId); } - } + } } @@ -1287,6 +1330,10 @@ void ClientConnection::handleChat(shared_ptr packet) int iPos; bool displayOnGui = true; + bool replacePlayer = false; + bool replaceEntitySource = false; + bool replaceItem = false; + wstring playerDisplayName = L""; wstring sourceDisplayName = L""; @@ -1337,134 +1384,213 @@ void ClientConnection::handleChat(shared_ptr packet) break; case ChatPacket::e_ChatDeathInFire: message=app.GetString(IDS_DEATH_INFIRE); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathOnFire: message=app.GetString(IDS_DEATH_ONFIRE); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathLava: message=app.GetString(IDS_DEATH_LAVA); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathInWall: message=app.GetString(IDS_DEATH_INWALL); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathDrown: message=app.GetString(IDS_DEATH_DROWN); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathStarve: message=app.GetString(IDS_DEATH_STARVE); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathCactus: message=app.GetString(IDS_DEATH_CACTUS); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathFall: message=app.GetString(IDS_DEATH_FALL); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathOutOfWorld: message=app.GetString(IDS_DEATH_OUTOFWORLD); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathGeneric: message=app.GetString(IDS_DEATH_GENERIC); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathExplosion: message=app.GetString(IDS_DEATH_EXPLOSION); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathMagic: message=app.GetString(IDS_DEATH_MAGIC); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathAnvil: message=app.GetString(IDS_DEATH_FALLING_ANVIL); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathFallingBlock: message=app.GetString(IDS_DEATH_FALLING_TILE); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathDragonBreath: message=app.GetString(IDS_DEATH_DRAGON_BREATH); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatDeathMob: message=app.GetString(IDS_DEATH_MOB); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); - message = replaceAll(message,L"{*SOURCE*}",app.getEntityName((eINSTANCEOF)packet->m_intArgs[0])); + replacePlayer = true; + replaceEntitySource = true; break; case ChatPacket::e_ChatDeathPlayer: message=app.GetString(IDS_DEATH_PLAYER); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); - message = replaceAll(message,L"{*SOURCE*}",sourceDisplayName); + replacePlayer = true; + replaceEntitySource = true; break; case ChatPacket::e_ChatDeathArrow: message=app.GetString(IDS_DEATH_ARROW); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); - if(packet->m_intArgs[0] == eTYPE_SERVERPLAYER) - { - message = replaceAll(message,L"{*SOURCE*}",sourceDisplayName); - } - else - { - message = replaceAll(message,L"{*SOURCE*}",app.getEntityName((eINSTANCEOF)packet->m_intArgs[0])); - } + replacePlayer = true; + replaceEntitySource = true; break; case ChatPacket::e_ChatDeathFireball: message=app.GetString(IDS_DEATH_FIREBALL); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); - if(packet->m_intArgs[0] == eTYPE_SERVERPLAYER) - { - message = replaceAll(message,L"{*SOURCE*}",packet->m_stringArgs[1]); - } - else - { - message = replaceAll(message,L"{*SOURCE*}",app.getEntityName((eINSTANCEOF)packet->m_intArgs[0])); - } + replacePlayer = true; + replaceEntitySource = true; break; case ChatPacket::e_ChatDeathThrown: message=app.GetString(IDS_DEATH_THROWN); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); - if(packet->m_intArgs[0] == eTYPE_SERVERPLAYER) - { - message = replaceAll(message,L"{*SOURCE*}",sourceDisplayName); - } - else - { - message = replaceAll(message,L"{*SOURCE*}",app.getEntityName((eINSTANCEOF)packet->m_intArgs[0])); - } + replacePlayer = true; + replaceEntitySource = true; break; case ChatPacket::e_ChatDeathIndirectMagic: message=app.GetString(IDS_DEATH_INDIRECT_MAGIC); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); - if(packet->m_intArgs[0] == eTYPE_SERVERPLAYER) - { - message = replaceAll(message,L"{*SOURCE*}",sourceDisplayName); - } - else - { - message = replaceAll(message,L"{*SOURCE*}",app.getEntityName((eINSTANCEOF)packet->m_intArgs[0])); - } + replacePlayer = true; + replaceEntitySource = true; break; case ChatPacket::e_ChatDeathThorns: message=app.GetString(IDS_DEATH_THORNS); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); - if(packet->m_intArgs[0] == eTYPE_SERVERPLAYER) - { - message = replaceAll(message,L"{*SOURCE*}",sourceDisplayName); - } - else - { - message = replaceAll(message,L"{*SOURCE*}",app.getEntityName((eINSTANCEOF)packet->m_intArgs[0])); - } + replacePlayer = true; + replaceEntitySource = true; + break; + + + case ChatPacket::e_ChatDeathFellAccidentLadder: + message=app.GetString(IDS_DEATH_FELL_ACCIDENT_LADDER); + replacePlayer = true; + break; + case ChatPacket::e_ChatDeathFellAccidentVines: + message=app.GetString(IDS_DEATH_FELL_ACCIDENT_VINES); + replacePlayer = true; + break; + case ChatPacket::e_ChatDeathFellAccidentWater: + message=app.GetString(IDS_DEATH_FELL_ACCIDENT_WATER); + replacePlayer = true; + break; + case ChatPacket::e_ChatDeathFellAccidentGeneric: + message=app.GetString(IDS_DEATH_FELL_ACCIDENT_GENERIC); + replacePlayer = true; + break; + case ChatPacket::e_ChatDeathFellKiller: + //message=app.GetString(IDS_DEATH_FELL_KILLER); + //replacePlayer = true; + //replaceEntitySource = true; + + // 4J Stu - The correct string for here, IDS_DEATH_FELL_KILLER is incorrect. We can't change localisation, so use a different string for now + message=app.GetString(IDS_DEATH_FALL); + replacePlayer = true; + break; + case ChatPacket::e_ChatDeathFellAssist: + message=app.GetString(IDS_DEATH_FELL_ASSIST); + replacePlayer = true; + replaceEntitySource = true; + break; + case ChatPacket::e_ChatDeathFellAssistItem: + message=app.GetString(IDS_DEATH_FELL_ASSIST_ITEM); + replacePlayer = true; + replaceEntitySource = true; + replaceItem = true; + break; + case ChatPacket::e_ChatDeathFellFinish: + message=app.GetString(IDS_DEATH_FELL_FINISH); + replacePlayer = true; + replaceEntitySource = true; + break; + case ChatPacket::e_ChatDeathFellFinishItem: + message=app.GetString(IDS_DEATH_FELL_FINISH_ITEM); + replacePlayer = true; + replaceEntitySource = true; + replaceItem = true; + break; + case ChatPacket::e_ChatDeathInFirePlayer: + message=app.GetString(IDS_DEATH_INFIRE_PLAYER); + replacePlayer = true; + replaceEntitySource = true; + break; + case ChatPacket::e_ChatDeathOnFirePlayer: + message=app.GetString(IDS_DEATH_ONFIRE_PLAYER); + replacePlayer = true; + replaceEntitySource = true; + break; + case ChatPacket::e_ChatDeathLavaPlayer: + message=app.GetString(IDS_DEATH_LAVA_PLAYER); + replacePlayer = true; + replaceEntitySource = true; + break; + case ChatPacket::e_ChatDeathDrownPlayer: + message=app.GetString(IDS_DEATH_DROWN_PLAYER); + replacePlayer = true; + replaceEntitySource = true; + break; + case ChatPacket::e_ChatDeathCactusPlayer: + message=app.GetString(IDS_DEATH_CACTUS_PLAYER); + replacePlayer = true; + replaceEntitySource = true; + break; + case ChatPacket::e_ChatDeathExplosionPlayer: + message=app.GetString(IDS_DEATH_EXPLOSION_PLAYER); + replacePlayer = true; + replaceEntitySource = true; + break; + case ChatPacket::e_ChatDeathWither: + message=app.GetString(IDS_DEATH_WITHER); + replacePlayer = true; + break; + case ChatPacket::e_ChatDeathPlayerItem: + message=app.GetString(IDS_DEATH_PLAYER_ITEM); + replacePlayer = true; + replaceEntitySource = true; + replaceItem = true; + break; + case ChatPacket::e_ChatDeathArrowItem: + message=app.GetString(IDS_DEATH_ARROW_ITEM); + replacePlayer = true; + replaceEntitySource = true; + replaceItem = true; + break; + case ChatPacket::e_ChatDeathFireballItem: + message=app.GetString(IDS_DEATH_FIREBALL_ITEM); + replacePlayer = true; + replaceEntitySource = true; + replaceItem = true; + break; + case ChatPacket::e_ChatDeathThrownItem: + message=app.GetString(IDS_DEATH_THROWN_ITEM); + replacePlayer = true; + replaceEntitySource = true; + replaceItem = true; + break; + case ChatPacket::e_ChatDeathIndirectMagicItem: + message=app.GetString(IDS_DEATH_INDIRECT_MAGIC_ITEM); + replacePlayer = true; + replaceEntitySource = true; + replaceItem = true; break; + case ChatPacket::e_ChatPlayerEnteredEnd: message=app.GetString(IDS_PLAYER_ENTERED_END); iPos=message.find(L"%s"); @@ -1498,6 +1624,9 @@ void ClientConnection::handleChat(shared_ptr packet) case ChatPacket::e_ChatPlayerMaxWolves: message=app.GetString(IDS_MAX_WOLVES_SPAWNED); break; + case ChatPacket::e_ChatPlayerMaxBats: + message=app.GetString(IDS_MAX_BATS_SPAWNED); + break; // Breeding case ChatPacket::e_ChatPlayerMaxBredPigsSheepCows: @@ -1535,23 +1664,23 @@ void ClientConnection::handleChat(shared_ptr packet) case ChatPacket::e_ChatCommandTeleportSuccess: message=app.GetString(IDS_COMMAND_TELEPORT_SUCCESS); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; if(packet->m_intArgs[0] == eTYPE_SERVERPLAYER) { - message = replaceAll(message,L"{*DESTINATION*}",packet->m_stringArgs[1]); + message = replaceAll(message,L"{*DESTINATION*}", sourceDisplayName); } else { - message = replaceAll(message,L"{*DESTINATION*}",app.getEntityName((eINSTANCEOF)packet->m_intArgs[0])); + message = replaceAll(message,L"{*DESTINATION*}", app.getEntityName((eINSTANCEOF)packet->m_intArgs[0])); } break; case ChatPacket::e_ChatCommandTeleportMe: message=app.GetString(IDS_COMMAND_TELEPORT_ME); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; case ChatPacket::e_ChatCommandTeleportToMe: message=app.GetString(IDS_COMMAND_TELEPORT_TO_ME); - message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + replacePlayer = true; break; default: @@ -1559,30 +1688,63 @@ void ClientConnection::handleChat(shared_ptr packet) break; } + + if(replacePlayer) + { + message = replaceAll(message,L"{*PLAYER*}",playerDisplayName); + } + + if(replaceEntitySource) + { + if(packet->m_intArgs[0] == eTYPE_SERVERPLAYER) + { + message = replaceAll(message,L"{*SOURCE*}", sourceDisplayName); + } + else + { + wstring entityName; + + // Check for a custom mob name + if (packet->m_stringArgs.size() >= 2 && !packet->m_stringArgs[1].empty()) + { + entityName = packet->m_stringArgs[1]; + } + else + { + entityName = app.getEntityName((eINSTANCEOF) packet->m_intArgs[0]); + } + + message = replaceAll(message,L"{*SOURCE*}", entityName); + } + } + + if (replaceItem) + { + message = replaceAll(message,L"{*ITEM*}", packet->m_stringArgs[2]); + } + // flag that a message is a death message - bool bIsDeathMessage = (packet->m_messageType>=ChatPacket::e_ChatDeathInFire) && (packet->m_messageType<=ChatPacket::e_ChatDeathDragonBreath); + bool bIsDeathMessage = (packet->m_messageType>=ChatPacket::e_ChatDeathInFire) && (packet->m_messageType<=ChatPacket::e_ChatDeathIndirectMagicItem); if( displayOnGui ) minecraft->gui->addMessage(message,m_userIndex, bIsDeathMessage); } void ClientConnection::handleAnimate(shared_ptr packet) { - shared_ptr e = getEntity(packet->id); - if (e == NULL) return; - if (packet->action == AnimatePacket::SWING) + shared_ptr e = getEntity(packet->id); + if (e == NULL) return; + if (packet->action == AnimatePacket::SWING) { - shared_ptr player = dynamic_pointer_cast(e); - if(player != NULL) player->swing(); - } + if (e->instanceof(eTYPE_LIVINGENTITY)) dynamic_pointer_cast(e)->swing(); + } else if (packet->action == AnimatePacket::HURT) { - e->animateHurt(); - } + e->animateHurt(); + } else if (packet->action == AnimatePacket::WAKE_UP) { - shared_ptr player = dynamic_pointer_cast(e); - if(player != NULL) player->stopSleepInBed(false, false, false); - } + if (e->instanceof(eTYPE_PLAYER)) dynamic_pointer_cast(e)->stopSleepInBed(false, false, false); + } else if (packet->action == AnimatePacket::RESPAWN) { } @@ -1597,27 +1759,27 @@ void ClientConnection::handleAnimate(shared_ptr packet) shared_ptr critParticle = shared_ptr( new CritParticle(minecraft->level, e, eParticleType_magicCrit) ); critParticle->CritParticlePostConstructor(); minecraft->particleEngine->add(critParticle); - } - else if (packet->action == AnimatePacket::EAT && dynamic_pointer_cast(e) != NULL) + } + else if ( (packet->action == AnimatePacket::EAT) && e->instanceof(eTYPE_REMOTEPLAYER) ) { - } + } } void ClientConnection::handleEntityActionAtPosition(shared_ptr packet) { - shared_ptr e = getEntity(packet->id); - if (e == NULL) return; - if (packet->action == EntityActionAtPositionPacket::START_SLEEP) + shared_ptr e = getEntity(packet->id); + if (e == NULL) return; + if (packet->action == EntityActionAtPositionPacket::START_SLEEP) { - shared_ptr player = dynamic_pointer_cast(e); - player->startSleepInBed(packet->x, packet->y, packet->z); + shared_ptr player = dynamic_pointer_cast(e); + player->startSleepInBed(packet->x, packet->y, packet->z); if( player == minecraft->localplayers[m_userIndex] ) { TelemetryManager->RecordEnemyKilledOrOvercome(m_userIndex, 0, player->y, 0, 0, 0, 0, eTelemetryInGame_UseBed); } - } + } } void ClientConnection::handlePreLogin(shared_ptr packet) @@ -1660,7 +1822,7 @@ void ClientConnection::handlePreLogin(shared_ptr packet) PlayerUID playerXuid = INVALID_XUID; if( ProfileManager.IsSignedInLive(idx) ) { - ProfileManager.GetXUID(idx,&playerXuid,true); + ProfileManager.GetXUID(idx,&playerXuid,true); } if( playerXuid != INVALID_XUID ) { @@ -1690,7 +1852,7 @@ void ClientConnection::handlePreLogin(shared_ptr packet) PlayerUID playerXuid = INVALID_XUID; if( ProfileManager.IsSignedInLive(m_userIndex) ) { - ProfileManager.GetXUID(m_userIndex,&playerXuid,true); + ProfileManager.GetXUID(m_userIndex,&playerXuid,true); } if( playerXuid != INVALID_XUID ) { @@ -1718,11 +1880,11 @@ void ClientConnection::handlePreLogin(shared_ptr packet) if( ProfileManager.IsSignedInLive(idx) ) { // need to use the XUID here - PlayerUID playerXUID = INVALID_XUID; + PlayerUID playerXUID = INVALID_XUID; if( !ProfileManager.IsGuest( idx ) ) { // Guest don't have an offline XUID as they cannot play offline, so use their online one - ProfileManager.GetXUID(idx,&playerXUID,true); + ProfileManager.GetXUID(idx,&playerXUID,true); } if( ProfileManager.AreXUIDSEqual(playerXUID,packet->m_playerXuids[i]) ) localPlayer = true; } @@ -1995,8 +2157,8 @@ void ClientConnection::handlePreLogin(shared_ptr packet) app.DebugPrintf("Exiting player %d on handling Pre-Login packet due UGC privileges: %d\n", m_userIndex, reason); UINT uiIDA[1]; uiIDA[0]=IDS_CONFIRM_OK; - if(!isFriendsWithHost) ui.RequestMessageBox( IDS_CANTJOIN_TITLE, IDS_NOTALLOWED_FRIENDSOFFRIENDS, uiIDA,1,m_userIndex,NULL,NULL, app.GetStringTable()); - else ui.RequestMessageBox( IDS_CANTJOIN_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL, uiIDA,1,m_userIndex,NULL,NULL, app.GetStringTable()); + if(!isFriendsWithHost) ui.RequestErrorMessage( IDS_CANTJOIN_TITLE, IDS_NOTALLOWED_FRIENDSOFFRIENDS, uiIDA,1,m_userIndex); + else ui.RequestErrorMessage( IDS_CANTJOIN_TITLE, IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL, uiIDA,1,m_userIndex); app.SetDisconnectReason( reason ); @@ -2029,7 +2191,9 @@ void ClientConnection::handlePreLogin(shared_ptr packet) app.DebugPrintf("Could not select texture pack %d from Pre-Login packet, requesting from host\n", packet->m_texturePackId); // 4J-PB - we need to upsell the texture pack to the player - //app.SetAction(m_userIndex,eAppAction_TexturePackRequired); +#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ + app.SetAction(m_userIndex,eAppAction_TexturePackRequired); +#endif // Let the player go into the game, and we'll check that they are using the right texture pack when in } } @@ -2039,12 +2203,12 @@ void ClientConnection::handlePreLogin(shared_ptr packet) Minecraft::GetInstance()->progressRenderer->progressStagePercentage((eCCPreLoginReceived * 100)/ (eCCConnected)); } // need to use the XUID here - PlayerUID offlineXUID = INVALID_XUID; + PlayerUID offlineXUID = INVALID_XUID; PlayerUID onlineXUID = INVALID_XUID; if( ProfileManager.IsSignedInLive(m_userIndex) ) { // Guest don't have an offline XUID as they cannot play offline, so use their online one - ProfileManager.GetXUID(m_userIndex,&onlineXUID,true); + ProfileManager.GetXUID(m_userIndex,&onlineXUID,true); } #ifdef __PSVITA__ if(CGameNetworkManager::usingAdhocMode() && onlineXUID.getOnlineID()[0] == 0) @@ -2060,7 +2224,7 @@ void ClientConnection::handlePreLogin(shared_ptr packet) #endif { // All other players we use their offline XUID so that they can play the game offline - ProfileManager.GetXUID(m_userIndex,&offlineXUID,false); + ProfileManager.GetXUID(m_userIndex,&offlineXUID,false); } BOOL allAllowed, friendsAllowed; ProfileManager.AllowedPlayerCreatedContent(m_userIndex,true,&allAllowed,&friendsAllowed); @@ -2074,25 +2238,25 @@ void ClientConnection::handlePreLogin(shared_ptr packet) } #else // 4J - removed - if (packet->loginKey.equals("-")) { - send(new LoginPacket(minecraft->user.name, SharedConstants.NETWORK_PROTOCOL_VERSION)); - } else { - try { - URL url = new URL("http://www.minecraft->net/game/joinserver.jsp?user=" + minecraft->user.name + "&sessionId=" + minecraft->user.sessionId + "&serverId=" + packet->loginKey); - BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream())); - String msg = br.readLine(); - br.close(); - - if (msg.equalsIgnoreCase("ok")) { - send(new LoginPacket(minecraft->user.name, SharedConstants.NETWORK_PROTOCOL_VERSION)); - } else { - connection.close("disconnect.loginFailedInfo", msg); - } - } catch (Exception e) { - e.printStackTrace(); - connection.close("disconnect.genericReason", "Internal client error: " + e.toString()); - } - } + if (packet->loginKey.equals("-")) { + send(new LoginPacket(minecraft->user.name, SharedConstants.NETWORK_PROTOCOL_VERSION)); + } else { + try { + URL url = new URL("http://www.minecraft->net/game/joinserver.jsp?user=" + minecraft->user.name + "&sessionId=" + minecraft->user.sessionId + "&serverId=" + packet->loginKey); + BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream())); + String msg = br.readLine(); + br.close(); + + if (msg.equalsIgnoreCase("ok")) { + send(new LoginPacket(minecraft->user.name, SharedConstants.NETWORK_PROTOCOL_VERSION)); + } else { + connection.close("disconnect.loginFailedInfo", msg); + } + } catch (Exception e) { + e.printStackTrace(); + connection.close("disconnect.genericReason", "Internal client error: " + e.toString()); + } + } #endif } @@ -2100,8 +2264,8 @@ void ClientConnection::close() { // If it's already done, then we don't need to do anything here. And in fact trying to do something could cause a crash if(done) return; - done = true; - connection->flush(); + done = true; + connection->flush(); connection->close(DisconnectPacket::eDisconnect_Closed); } @@ -2113,7 +2277,7 @@ void ClientConnection::handleAddMob(shared_ptr packet) float yRot = packet->yRot * 360 / 256.0f; float xRot = packet->xRot * 360 / 256.0f; - shared_ptr mob = dynamic_pointer_cast(EntityIO::newById(packet->type, level)); + shared_ptr mob = dynamic_pointer_cast(EntityIO::newById(packet->type, level)); mob->xp = packet->x; mob->yp = packet->y; mob->zp = packet->z; @@ -2160,43 +2324,83 @@ void ClientConnection::handleAddMob(shared_ptr packet) void ClientConnection::handleSetTime(shared_ptr packet) { - minecraft->level->setTime(packet->time); + minecraft->level->setGameTime(packet->gameTime); + minecraft->level->setDayTime(packet->dayTime); } void ClientConnection::handleSetSpawn(shared_ptr packet) { - //minecraft->player->setRespawnPosition(new Pos(packet->x, packet->y, packet->z)); - minecraft->localplayers[m_userIndex]->setRespawnPosition(new Pos(packet->x, packet->y, packet->z)); - minecraft->level->getLevelData()->setSpawn(packet->x, packet->y, packet->z); + //minecraft->player->setRespawnPosition(new Pos(packet->x, packet->y, packet->z)); + minecraft->localplayers[m_userIndex]->setRespawnPosition(new Pos(packet->x, packet->y, packet->z), true); + minecraft->level->getLevelData()->setSpawn(packet->x, packet->y, packet->z); } -void ClientConnection::handleRidePacket(shared_ptr packet) +void ClientConnection::handleEntityLinkPacket(shared_ptr packet) { - shared_ptr rider = getEntity(packet->riderId); - shared_ptr ridden = getEntity(packet->riddenId); + shared_ptr sourceEntity = getEntity(packet->sourceId); + shared_ptr destEntity = getEntity(packet->destId); - shared_ptr boat = dynamic_pointer_cast(ridden); - //if (packet->riderId == minecraft->player->entityId) rider = minecraft->player; - if (packet->riderId == minecraft->localplayers[m_userIndex]->entityId) + // 4J: If the destination entity couldn't be found, defer handling of this packet + // This was added to support leashing (the entity link packet is sent before the add entity packet) + if (destEntity == NULL && packet->destId >= 0) { - rider = minecraft->localplayers[m_userIndex]; + // We don't handle missing source entities because it shouldn't happen + assert(!(sourceEntity == NULL && packet->sourceId >= 0)); - if (boat) boat->setDoLerp(false); + deferredEntityLinkPackets.push_back(DeferredEntityLinkPacket(packet)); + return; } - else if (boat) + + if (packet->type == SetEntityLinkPacket::RIDING) { - boat->setDoLerp(true); - } - if (rider == NULL) return; + bool displayMountMessage = false; + if (packet->sourceId == Minecraft::GetInstance()->localplayers[m_userIndex].get()->entityId) + { + sourceEntity = Minecraft::GetInstance()->localplayers[m_userIndex]; - rider->ride(ridden); + if (destEntity != NULL && destEntity->instanceof(eTYPE_BOAT)) (dynamic_pointer_cast(destEntity))->setDoLerp(false); + + displayMountMessage = (sourceEntity->riding == NULL && destEntity != NULL); + } + else if (destEntity != NULL && destEntity->instanceof(eTYPE_BOAT)) + { + (dynamic_pointer_cast(destEntity))->setDoLerp(true); + } + + if (sourceEntity == NULL) return; + + sourceEntity->ride(destEntity); + + // 4J TODO: pretty sure this message is a tooltip so not needed + /* + if (displayMountMessage) { + Options options = minecraft.options; + minecraft.gui.setOverlayMessage(I18n.get("mount.onboard", Options.getTranslatedKeyMessage(options.keySneak.key)), false); + } + */ + } + else if (packet->type == SetEntityLinkPacket::LEASH) + { + if ( (sourceEntity != NULL) && sourceEntity->instanceof(eTYPE_MOB) ) + { + if (destEntity != NULL) + { + + (dynamic_pointer_cast(sourceEntity))->setLeashedTo(destEntity, false); + } + else + { + (dynamic_pointer_cast(sourceEntity))->dropLeash(false, false); + } + } + } } void ClientConnection::handleEntityEvent(shared_ptr packet) { - shared_ptr e = getEntity(packet->entityId); - if (e != NULL) e->handleEntityEvent(packet->eventId); + shared_ptr e = getEntity(packet->entityId); + if (e != NULL) e->handleEntityEvent(packet->eventId); } shared_ptr ClientConnection::getEntity(int entityId) @@ -2326,9 +2530,8 @@ void ClientConnection::handleTextureAndGeometry(shared_ptr packet) { shared_ptr e = getEntity(packet->id); - if (e == NULL) return; + if ( (e == NULL) || !e->instanceof(eTYPE_PLAYER) ) return; shared_ptr player = dynamic_pointer_cast(e); - if( e == NULL) return; bool isLocalPlayer = false; for( int i = 0; i < XUSER_MAX_COUNT; i++ ) @@ -2426,11 +2629,11 @@ void ClientConnection::handleTextureAndGeometryChange(shared_ptr packet) { - //if (packet->dimension != minecraft->player->dimension) + //if (packet->dimension != minecraft->player->dimension) if( packet->dimension != minecraft->localplayers[m_userIndex]->dimension || packet->mapSeed != minecraft->localplayers[m_userIndex]->level->getSeed() ) { int oldDimension = minecraft->localplayers[m_userIndex]->dimension; - started = false; + started = false; // Remove client connection from this level level->removeClientConnection(this, false); @@ -2474,7 +2677,7 @@ void ClientConnection::handleRespawn(shared_ptr packet) //minecraft->player->dimension = packet->dimension; minecraft->localplayers[m_userIndex]->dimension = packet->dimension; - //minecraft->setScreen(new ReceivingLevelScreen(this)); + //minecraft->setScreen(new ReceivingLevelScreen(this)); // minecraft->addPendingLocalConnection(m_userIndex, this); #ifdef _XBOX @@ -2524,15 +2727,15 @@ void ClientConnection::handleRespawn(shared_ptr packet) } app.SetAction( m_userIndex, eAppAction_WaitForDimensionChangeComplete); - } + } - //minecraft->respawnPlayer(minecraft->player->GetXboxPad(),true, packet->dimension); + //minecraft->respawnPlayer(minecraft->player->GetXboxPad(),true, packet->dimension); // Wrap respawnPlayer call up in code to set & restore the player/gamemode etc. as some things // in there assume that we are set up for the player that the respawn is coming in for int oldIndex = minecraft->getLocalPlayerIdx(); minecraft->setLocalPlayerIdx(m_userIndex); - minecraft->respawnPlayer(minecraft->localplayers[m_userIndex]->GetXboxPad(),packet->dimension,packet->m_newEntityId); + minecraft->respawnPlayer(minecraft->localplayers[m_userIndex]->GetXboxPad(),packet->dimension,packet->m_newEntityId); ((MultiPlayerGameMode *) minecraft->localgameModes[m_userIndex])->setLocalMode(packet->playerGameType); minecraft->setLocalPlayerIdx(oldIndex); } @@ -2543,7 +2746,7 @@ void ClientConnection::handleExplosion(shared_ptr packet) { //app.DebugPrintf("Received ExplodePacket with explosion data\n"); PIXBeginNamedEvent(0,"Handling explosion"); - Explosion *e = new Explosion(minecraft->level, nullptr, packet->x, packet->y, packet->z, packet->r); + Explosion *e = new Explosion(minecraft->level, nullptr, packet->x, packet->y, packet->z, packet->r); PIXBeginNamedEvent(0,"Finalizing"); // Fix for #81758 - TCR 006 BAS Non-Interactive Pause: TU9: Performance: Gameplay: After detonating bunch of TNT, game enters unresponsive state for couple of seconds. @@ -2575,9 +2778,38 @@ void ClientConnection::handleContainerOpen(shared_ptr packe shared_ptr player = minecraft->localplayers[m_userIndex]; switch(packet->type) { + case ContainerOpenPacket::BONUS_CHEST: + case ContainerOpenPacket::LARGE_CHEST: + case ContainerOpenPacket::ENDER_CHEST: case ContainerOpenPacket::CONTAINER: + case ContainerOpenPacket::MINECART_CHEST: { - if( player->openContainer(shared_ptr( new SimpleContainer(packet->title, packet->size) ))) + int chestString; + switch (packet->type) + { + case ContainerOpenPacket::MINECART_CHEST: chestString = IDS_ITEM_MINECART; break; + case ContainerOpenPacket::BONUS_CHEST: chestString = IDS_BONUS_CHEST; break; + case ContainerOpenPacket::LARGE_CHEST: chestString = IDS_CHEST_LARGE; break; + case ContainerOpenPacket::ENDER_CHEST: chestString = IDS_TILE_ENDERCHEST; break; + case ContainerOpenPacket::CONTAINER: chestString = IDS_CHEST; break; + default: assert(false); chestString = -1; break; + } + + if( player->openContainer(shared_ptr( new SimpleContainer(chestString, packet->title, packet->customName, packet->size) ))) + { + player->containerMenu->containerId = packet->containerId; + } + else + { + failed = true; + } + } + break; + case ContainerOpenPacket::HOPPER: + { + shared_ptr hopper = shared_ptr(new HopperTileEntity()); + if (packet->customName) hopper->setCustomName(packet->title); + if(player->openHopper(hopper)) { player->containerMenu->containerId = packet->containerId; } @@ -2589,7 +2821,9 @@ void ClientConnection::handleContainerOpen(shared_ptr packe break; case ContainerOpenPacket::FURNACE: { - if( player->openFurnace(shared_ptr( new FurnaceTileEntity() )) ) + shared_ptr furnace = shared_ptr(new FurnaceTileEntity()); + if (packet->customName) furnace->setCustomName(packet->title); + if(player->openFurnace(furnace)) { player->containerMenu->containerId = packet->containerId; } @@ -2601,7 +2835,10 @@ void ClientConnection::handleContainerOpen(shared_ptr packe break; case ContainerOpenPacket::BREWING_STAND: { - if( player->openBrewingStand(shared_ptr( new BrewingStandTileEntity() )) ) + shared_ptr brewingStand = shared_ptr(new BrewingStandTileEntity()); + if (packet->customName) brewingStand->setCustomName(packet->title); + + if( player->openBrewingStand(brewingStand)) { player->containerMenu->containerId = packet->containerId; } @@ -2611,9 +2848,27 @@ void ClientConnection::handleContainerOpen(shared_ptr packe } } break; + case ContainerOpenPacket::DROPPER: + { + shared_ptr dropper = shared_ptr(new DropperTileEntity()); + if (packet->customName) dropper->setCustomName(packet->title); + + if( player->openTrap(dropper)) + { + player->containerMenu->containerId = packet->containerId; + } + else + { + failed = true; + } + } + break; case ContainerOpenPacket::TRAP: { - if( player->openTrap(shared_ptr( new DispenserTileEntity() )) ) + shared_ptr dispenser = shared_ptr(new DispenserTileEntity()); + if (packet->customName) dispenser->setCustomName(packet->title); + + if( player->openTrap(dispenser)) { player->containerMenu->containerId = packet->containerId; } @@ -2637,7 +2892,7 @@ void ClientConnection::handleContainerOpen(shared_ptr packe break; case ContainerOpenPacket::ENCHANTMENT: { - if( player->startEnchanting(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z)) ) + if( player->startEnchanting(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z), packet->customName ? packet->title : L"") ) { player->containerMenu->containerId = packet->containerId; } @@ -2649,9 +2904,9 @@ void ClientConnection::handleContainerOpen(shared_ptr packe break; case ContainerOpenPacket::TRADER_NPC: { - shared_ptr csm = shared_ptr(new ClientSideMerchant(player,packet->title)); + shared_ptr csm = shared_ptr(new ClientSideMerchant(player, packet->title)); csm->createContainer(); - if(player->openTrading(csm)) + if(player->openTrading(csm, packet->customName ? packet->title : L"")) { player->containerMenu->containerId = packet->containerId; } @@ -2661,6 +2916,21 @@ void ClientConnection::handleContainerOpen(shared_ptr packe } } break; + case ContainerOpenPacket::BEACON: + { + shared_ptr beacon = shared_ptr(new BeaconTileEntity()); + if (packet->customName) beacon->setCustomName(packet->title); + + if(player->openBeacon(beacon)) + { + player->containerMenu->containerId = packet->containerId; + } + else + { + failed = true; + } + } + break; case ContainerOpenPacket::REPAIR_TABLE: { if(player->startRepairing(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z))) @@ -2673,7 +2943,42 @@ void ClientConnection::handleContainerOpen(shared_ptr packe } } break; - }; + case ContainerOpenPacket::HORSE: + { + shared_ptr entity = dynamic_pointer_cast( getEntity(packet->entityId) ); + int iTitle = IDS_CONTAINER_ANIMAL; + switch(entity->getType()) + { + case EntityHorse::TYPE_DONKEY: + iTitle = IDS_DONKEY; + break; + case EntityHorse::TYPE_MULE: + iTitle = IDS_MULE; + break; + }; + if(player->openHorseInventory(dynamic_pointer_cast(entity), shared_ptr(new AnimalChest(iTitle, packet->title, packet->customName, packet->size)))) + { + player->containerMenu->containerId = packet->containerId; + } + else + { + failed = true; + } + } + break; + case ContainerOpenPacket::FIREWORKS: + { + if( player->openFireworks(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z)) ) + { + player->containerMenu->containerId = packet->containerId; + } + else + { + failed = true; + } + } + break; + } if(failed) { @@ -2694,13 +2999,13 @@ void ClientConnection::handleContainerOpen(shared_ptr packe void ClientConnection::handleContainerSetSlot(shared_ptr packet) { shared_ptr player = minecraft->localplayers[m_userIndex]; - if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_CARRIED ) + if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_CARRIED ) { - player->inventory->setCarried(packet->item); - } + player->inventory->setCarried(packet->item); + } else { - if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_INVENTORY) + if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_INVENTORY) { // 4J Stu - Reworked a bit to fix a bug where things being collected while the creative menu was up replaced items in the creative menu if(packet->slot >= 36 && packet->slot < 36 + 9) @@ -2718,72 +3023,90 @@ void ClientConnection::handleContainerSetSlot(shared_ptr } else if (packet->containerId == player->containerMenu->containerId) { - player->containerMenu->setItem(packet->slot, packet->item); - } - } + player->containerMenu->setItem(packet->slot, packet->item); + } + } } void ClientConnection::handleContainerAck(shared_ptr packet) { shared_ptr player = minecraft->localplayers[m_userIndex]; - AbstractContainerMenu *menu = NULL; - if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_INVENTORY) + AbstractContainerMenu *menu = NULL; + if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_INVENTORY) { - menu = player->inventoryMenu; - } + menu = player->inventoryMenu; + } else if (packet->containerId == player->containerMenu->containerId) { - menu = player->containerMenu; - } - if (menu != NULL) + menu = player->containerMenu; + } + if (menu != NULL) { - if (!packet->accepted) + if (!packet->accepted) { - send( shared_ptr( new ContainerAckPacket(packet->containerId, packet->uid, true) )); - } - } + send( shared_ptr( new ContainerAckPacket(packet->containerId, packet->uid, true) )); + } + } } void ClientConnection::handleContainerContent(shared_ptr packet) { shared_ptr player = minecraft->localplayers[m_userIndex]; - if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_INVENTORY) + if (packet->containerId == AbstractContainerMenu::CONTAINER_ID_INVENTORY) { - player->inventoryMenu->setAll(&packet->items); - } + player->inventoryMenu->setAll(&packet->items); + } else if (packet->containerId == player->containerMenu->containerId) { - player->containerMenu->setAll(&packet->items); - } + player->containerMenu->setAll(&packet->items); + } +} + +void ClientConnection::handleTileEditorOpen(shared_ptr packet) +{ + shared_ptr tileEntity = level->getTileEntity(packet->x, packet->y, packet->z); + if (tileEntity != NULL) + { + minecraft->localplayers[m_userIndex]->openTextEdit(tileEntity); + } + else if (packet->editorType == TileEditorOpenPacket::SIGN) + { + shared_ptr localSignDummy = shared_ptr(new SignTileEntity()); + localSignDummy->setLevel(level); + localSignDummy->x = packet->x; + localSignDummy->y = packet->y; + localSignDummy->z = packet->z; + minecraft->player->openTextEdit(localSignDummy); + } } void ClientConnection::handleSignUpdate(shared_ptr packet) { app.DebugPrintf("ClientConnection::handleSignUpdate - "); - if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z)) + if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z)) { - shared_ptr te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z); + shared_ptr te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z); // 4J-PB - on a client connecting, the line below fails - if (dynamic_pointer_cast(te) != NULL) + if (dynamic_pointer_cast(te) != NULL) { - shared_ptr ste = dynamic_pointer_cast(te); - for (int i = 0; i < MAX_SIGN_LINES; i++) + shared_ptr ste = dynamic_pointer_cast(te); + for (int i = 0; i < MAX_SIGN_LINES; i++) { ste->SetMessage(i,packet->lines[i]); - } + } app.DebugPrintf("verified = %d\tCensored = %d\n",packet->m_bVerified,packet->m_bCensored); ste->SetVerified(packet->m_bVerified); ste->SetCensored(packet->m_bCensored); - ste->setChanged(); - } + ste->setChanged(); + } else { app.DebugPrintf("dynamic_pointer_cast(te) == NULL\n"); } - } + } else { app.DebugPrintf("hasChunkAt failed\n"); @@ -2802,14 +3125,14 @@ void ClientConnection::handleTileEntityData(shared_ptr pac { dynamic_pointer_cast(te)->load(packet->tag); } - //else if (packet.type == TileEntityDataPacket.TYPE_ADV_COMMAND && (te instanceof CommandBlockEntity)) - //{ - // ((CommandBlockEntity) te).load(packet.tag); - //} - //else if (packet.type == TileEntityDataPacket.TYPE_BEACON && (te instanceof BeaconTileEntity)) - //{ - // ((BeaconTileEntity) te).load(packet.tag); - //} + else if (packet->type == TileEntityDataPacket::TYPE_ADV_COMMAND && dynamic_pointer_cast(te) != NULL) + { + dynamic_pointer_cast(te)->load(packet->tag); + } + else if (packet->type == TileEntityDataPacket::TYPE_BEACON && dynamic_pointer_cast(te) != NULL) + { + dynamic_pointer_cast(te)->load(packet->tag); + } else if (packet->type == TileEntityDataPacket::TYPE_SKULL && dynamic_pointer_cast(te) != NULL) { dynamic_pointer_cast(te)->load(packet->tag); @@ -2820,26 +3143,26 @@ void ClientConnection::handleTileEntityData(shared_ptr pac void ClientConnection::handleContainerSetData(shared_ptr packet) { - onUnhandledPacket(packet); - if (minecraft->localplayers[m_userIndex]->containerMenu != NULL && minecraft->localplayers[m_userIndex]->containerMenu->containerId == packet->containerId) + onUnhandledPacket(packet); + if (minecraft->localplayers[m_userIndex]->containerMenu != NULL && minecraft->localplayers[m_userIndex]->containerMenu->containerId == packet->containerId) { - minecraft->localplayers[m_userIndex]->containerMenu->setData(packet->id, packet->value); - } + minecraft->localplayers[m_userIndex]->containerMenu->setData(packet->id, packet->value); + } } void ClientConnection::handleSetEquippedItem(shared_ptr packet) { - shared_ptr entity = getEntity(packet->entity); - if (entity != NULL) + shared_ptr entity = getEntity(packet->entity); + if (entity != NULL) { // 4J Stu - Brought forward change from 1.3 to fix #64688 - Customer Encountered: TU7: Content: Art: Aura of enchanted item is not displayed for other players in online game - entity->setEquippedSlot(packet->slot, packet->getItem() ); - } + entity->setEquippedSlot(packet->slot, packet->getItem() ); + } } void ClientConnection::handleContainerClose(shared_ptr packet) { - minecraft->localplayers[m_userIndex]->closeContainer(); + minecraft->localplayers[m_userIndex]->clientSideCloseContainer(); } void ClientConnection::handleTileEvent(shared_ptr packet) @@ -2861,24 +3184,24 @@ bool ClientConnection::canHandleAsyncPackets() void ClientConnection::handleGameEvent(shared_ptr gameEventPacket) { - int event = gameEventPacket->_event; + int event = gameEventPacket->_event; int param = gameEventPacket->param; - if (event >= 0 && event < GameEventPacket::EVENT_LANGUAGE_ID_LENGTH) + if (event >= 0 && event < GameEventPacket::EVENT_LANGUAGE_ID_LENGTH) { - if (GameEventPacket::EVENT_LANGUAGE_ID[event] > 0) // 4J - was NULL check + if (GameEventPacket::EVENT_LANGUAGE_ID[event] > 0) // 4J - was NULL check { minecraft->localplayers[m_userIndex]->displayClientMessage(GameEventPacket::EVENT_LANGUAGE_ID[event]); - } - } - if (event == GameEventPacket::START_RAINING) + } + } + if (event == GameEventPacket::START_RAINING) { - level->getLevelData()->setRaining(true); - level->setRainLevel(1); - } + level->getLevelData()->setRaining(true); + level->setRainLevel(1); + } else if (event == GameEventPacket::STOP_RAINING) { - level->getLevelData()->setRaining(false); - level->setRainLevel(0); + level->getLevelData()->setRaining(false); + level->setRainLevel(0); } else if (event == GameEventPacket::CHANGE_GAME_MODE) { @@ -2923,6 +3246,11 @@ void ClientConnection::handleGameEvent(shared_ptr gameEventPack { if(!g_NetworkManager.IsHost() ) app.SetGameStarted(true); } + else if ( event == GameEventPacket::SUCCESSFUL_BOW_HIT ) + { + shared_ptr player = minecraft->localplayers[m_userIndex]; + level->playLocalSound(player->x, player->y + player->getHeadHeight(), player->z, eSoundType_RANDOM_BOW_HIT , 0.18f, 0.45f, false); + } } void ClientConnection::handleComplexItemData(shared_ptr packet) @@ -2941,26 +3269,27 @@ void ClientConnection::handleComplexItemData(shared_ptr p void ClientConnection::handleLevelEvent(shared_ptr packet) { - switch(packet->type) + if (packet->type == LevelEvent::SOUND_DRAGON_DEATH) { - case LevelEvent::SOUND_DRAGON_DEATH: + for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) { - Minecraft *pMinecraft = Minecraft::GetInstance(); - for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) + if(minecraft->localplayers[i] != NULL && minecraft->localplayers[i]->level != NULL && minecraft->localplayers[i]->level->dimension->id == 1) { - if(pMinecraft->localplayers[i] != NULL && pMinecraft->localplayers[i]->level != NULL && pMinecraft->localplayers[i]->level->dimension->id == 1) - { - pMinecraft->localplayers[i]->awardStat(GenericStats::completeTheEnd(),GenericStats::param_noArgs()); - } + minecraft->localplayers[i]->awardStat(GenericStats::completeTheEnd(),GenericStats::param_noArgs()); } } - minecraft->level->levelEvent(packet->type, packet->x, packet->y, packet->z, packet->data); + } - break; - default: + if (packet->isGlobalEvent()) + { + minecraft->level->globalLevelEvent(packet->type, packet->x, packet->y, packet->z, packet->data); + } + else + { minecraft->level->levelEvent(packet->type, packet->x, packet->y, packet->z, packet->data); - break; } + + minecraft->level->levelEvent(packet->type, packet->x, packet->y, packet->z, packet->data); } void ClientConnection::handleAwardStat(shared_ptr packet) @@ -2971,17 +3300,21 @@ void ClientConnection::handleAwardStat(shared_ptr packet) void ClientConnection::handleUpdateMobEffect(shared_ptr packet) { shared_ptr e = getEntity(packet->entityId); - if (e == NULL || dynamic_pointer_cast(e) == NULL) return; + if ( (e == NULL) || !e->instanceof(eTYPE_LIVINGENTITY) ) return; + + //( dynamic_pointer_cast(e) )->addEffect(new MobEffectInstance(packet->effectId, packet->effectDurationTicks, packet->effectAmplifier)); - ( dynamic_pointer_cast(e) )->addEffect(new MobEffectInstance(packet->effectId, packet->effectDurationTicks, packet->effectAmplifier)); + MobEffectInstance *mobEffectInstance = new MobEffectInstance(packet->effectId, packet->effectDurationTicks, packet->effectAmplifier); + mobEffectInstance->setNoCounter(packet->isSuperLongDuration()); + dynamic_pointer_cast(e)->addEffect(mobEffectInstance); } void ClientConnection::handleRemoveMobEffect(shared_ptr packet) { shared_ptr e = getEntity(packet->entityId); - if (e == NULL || dynamic_pointer_cast(e) == NULL) return; + if ( (e == NULL) || !e->instanceof(eTYPE_LIVINGENTITY) ) return; - ( dynamic_pointer_cast(e) )->removeEffectNoUpdate(packet->effectId); + ( dynamic_pointer_cast(e) )->removeEffectNoUpdate(packet->effectId); } bool ClientConnection::isServerPacketListener() @@ -3006,7 +3339,7 @@ void ClientConnection::handlePlayerInfo(shared_ptr packet) app.UpdatePlayerInfo(packet->m_networkSmallId, packet->m_playerColourIndex, packet->m_playerPrivileges); shared_ptr entity = getEntity(packet->m_entityId); - if(entity != NULL && entity->GetType() == eTYPE_PLAYER) + if(entity != NULL && entity->instanceof(eTYPE_PLAYER)) { shared_ptr player = dynamic_pointer_cast(entity); player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_All, packet->m_playerPrivileges); @@ -3154,11 +3487,12 @@ void ClientConnection::handlePlayerAbilities(shared_ptr p player->abilities.invulnerable = playerAbilitiesPacket->isInvulnerable(); player->abilities.mayfly = playerAbilitiesPacket->canFly(); player->abilities.setFlyingSpeed(playerAbilitiesPacket->getFlyingSpeed()); + player->abilities.setWalkingSpeed(playerAbilitiesPacket->getWalkingSpeed()); } void ClientConnection::handleSoundEvent(shared_ptr packet) { - minecraft->level->playLocalSound(packet->getX(), packet->getY(), packet->getZ(), packet->getSound(), packet->getVolume(), packet->getPitch()); + minecraft->level->playLocalSound(packet->getX(), packet->getY(), packet->getZ(), packet->getSound(), packet->getVolume(), packet->getPitch(), false); } void ClientConnection::handleCustomPayload(shared_ptr customPayloadPacket) @@ -3297,7 +3631,7 @@ int ClientConnection::HostDisconnectReturned(void *pParam,int iPad,C4JStorage::E UINT uiIDA[2]; uiIDA[0]=IDS_CONFIRM_CANCEL; uiIDA[1]=IDS_CONFIRM_OK; - ui.RequestMessageBox(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&ClientConnection::ExitGameAndSaveReturned,NULL, app.GetStringTable()); + ui.RequestErrorMessage(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&ClientConnection::ExitGameAndSaveReturned,NULL); } else #else @@ -3312,7 +3646,7 @@ int ClientConnection::HostDisconnectReturned(void *pParam,int iPad,C4JStorage::E UINT uiIDA[2]; uiIDA[0]=IDS_CONFIRM_CANCEL; uiIDA[1]=IDS_CONFIRM_OK; - ui.RequestMessageBox(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&ClientConnection::ExitGameAndSaveReturned,NULL, app.GetStringTable()); + ui.RequestErrorMessage(IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2, ProfileManager.GetPrimaryPad(),&ClientConnection::ExitGameAndSaveReturned,NULL); } else #endif @@ -3360,3 +3694,208 @@ wstring ClientConnection::GetDisplayNameByGamertag(wstring gamertag) return gamertag; #endif } + +void ClientConnection::handleAddObjective(shared_ptr packet) +{ +#if 0 + Scoreboard scoreboard = level->getScoreboard(); + + if (packet->method == SetObjectivePacket::METHOD_ADD) + { + Objective objective = scoreboard->addObjective(packet->objectiveName, ObjectiveCriteria::DUMMY); + objective->setDisplayName(packet->displayName); + } + else + { + Objective objective = scoreboard->getObjective(packet->objectiveName); + + if (packet->method == SetObjectivePacket::METHOD_REMOVE) + { + scoreboard->removeObjective(objective); + } + else if (packet->method == SetObjectivePacket::METHOD_CHANGE) + { + objective->setDisplayName(packet->displayName); + } + } +#endif +} + +void ClientConnection::handleSetScore(shared_ptr packet) +{ +#if 0 + Scoreboard scoreboard = level->getScoreboard(); + Objective objective = scoreboard->getObjective(packet->objectiveName); + + if (packet->method == SetScorePacket::METHOD_CHANGE) + { + Score score = scoreboard->getPlayerScore(packet->owner, objective); + score->setScore(packet->score); + } + else if (packet->method == SetScorePacket::METHOD_REMOVE) + { + scoreboard->resetPlayerScore(packet->owner); + } +#endif +} + +void ClientConnection::handleSetDisplayObjective(shared_ptr packet) +{ +#if 0 + Scoreboard scoreboard = level->getScoreboard(); + + if (packet->objectiveName->length() == 0) + { + scoreboard->setDisplayObjective(packet->slot, null); + } + else + { + Objective objective = scoreboard->getObjective(packet->objectiveName); + scoreboard->setDisplayObjective(packet->slot, objective); + } +#endif +} + +void ClientConnection::handleSetPlayerTeamPacket(shared_ptr packet) +{ +#if 0 + Scoreboard scoreboard = level->getScoreboard(); + PlayerTeam *team; + + if (packet->method == SetPlayerTeamPacket::METHOD_ADD) + { + team = scoreboard->addPlayerTeam(packet->name); + } + else + { + team = scoreboard->getPlayerTeam(packet->name); + } + + if (packet->method == SetPlayerTeamPacket::METHOD_ADD || packet->method == SetPlayerTeamPacket::METHOD_CHANGE) + { + team->setDisplayName(packet->displayName); + team->setPrefix(packet->prefix); + team->setSuffix(packet->suffix); + team->unpackOptions(packet->options); + } + + if (packet->method == SetPlayerTeamPacket::METHOD_ADD || packet->method == SetPlayerTeamPacket::METHOD_JOIN) + { + for (int i = 0; i < packet->players.size(); i++) + { + scoreboard->addPlayerToTeam(packet->players[i], team); + } + } + + if (packet->method == SetPlayerTeamPacket::METHOD_LEAVE) + { + for (int i = 0; i < packet->players.size(); i++) + { + scoreboard->removePlayerFromTeam(packet->players[i], team); + } + } + + if (packet->method == SetPlayerTeamPacket::METHOD_REMOVE) + { + scoreboard->removePlayerTeam(team); + } +#endif +} + +void ClientConnection::handleParticleEvent(shared_ptr packet) +{ + for (int i = 0; i < packet->getCount(); i++) + { + double xVarience = random->nextGaussian() * packet->getXDist(); + double yVarience = random->nextGaussian() * packet->getYDist(); + double zVarience = random->nextGaussian() * packet->getZDist(); + double xa = random->nextGaussian() * packet->getMaxSpeed(); + double ya = random->nextGaussian() * packet->getMaxSpeed(); + double za = random->nextGaussian() * packet->getMaxSpeed(); + + // TODO: determine particle ID from name + assert(0); + ePARTICLE_TYPE particleId = eParticleType_heart; + + level->addParticle(particleId, packet->getX() + xVarience, packet->getY() + yVarience, packet->getZ() + zVarience, xa, ya, za); + } +} + +void ClientConnection::handleUpdateAttributes(shared_ptr packet) +{ + shared_ptr entity = getEntity(packet->getEntityId()); + if (entity == NULL) return; + + if ( !entity->instanceof(eTYPE_LIVINGENTITY) ) + { + // Entity is not a living entity! + assert(0); + } + + BaseAttributeMap *attributes = (dynamic_pointer_cast(entity))->getAttributes(); + unordered_set attributeSnapshots = packet->getValues(); + for (AUTO_VAR(it,attributeSnapshots.begin()); it != attributeSnapshots.end(); ++it) + { + UpdateAttributesPacket::AttributeSnapshot *attribute = *it; + AttributeInstance *instance = attributes->getInstance(attribute->getId()); + + if (instance == NULL) + { + // 4J - TODO: revisit, not familiar with the attribute system, why are we passing in MIN_NORMAL (Java's smallest non-zero value conforming to IEEE Standard 754 (?)) and MAX_VALUE + instance = attributes->registerAttribute(new RangedAttribute(attribute->getId(), 0, Double::MIN_NORMAL, Double::MAX_VALUE)); + } + + instance->setBaseValue(attribute->getBase()); + instance->removeModifiers(); + + unordered_set *modifiers = attribute->getModifiers(); + + for (AUTO_VAR(it2,modifiers->begin()); it2 != modifiers->end(); ++it2) + { + AttributeModifier* modifier = *it2; + instance->addModifier(new AttributeModifier(modifier->getId(), modifier->getAmount(), modifier->getOperation() ) ); + } + } +} + +// 4J: Check for deferred entity link packets related to this entity ID and handle them +void ClientConnection::checkDeferredEntityLinkPackets(int newEntityId) +{ + if (deferredEntityLinkPackets.empty()) return; + + for (int i = 0; i < deferredEntityLinkPackets.size(); i++) + { + DeferredEntityLinkPacket *deferred = &deferredEntityLinkPackets[i]; + + bool remove = false; + + // Only consider recently deferred packets + int tickInterval = GetTickCount() - deferred->m_recievedTick; + if (tickInterval < MAX_ENTITY_LINK_DEFERRAL_INTERVAL) + { + // Note: we assume it's the destination entity + if (deferred->m_packet->destId == newEntityId) + { + handleEntityLinkPacket(deferred->m_packet); + remove = true; + } + } + else + { + // This is an old packet, remove (shouldn't really come up but seems prudent) + remove = true; + } + + if (remove) + { + deferredEntityLinkPackets.erase(deferredEntityLinkPackets.begin() + i); + i--; + } + } +} + +ClientConnection::DeferredEntityLinkPacket::DeferredEntityLinkPacket(shared_ptr packet) +{ + m_recievedTick = GetTickCount(); + m_packet = packet; +} \ No newline at end of file -- cgit v1.2.3