diff --git a/source/BlockID.cpp b/source/BlockID.cpp index 38b0b6ad4..c3bd3c750 100644 --- a/source/BlockID.cpp +++ b/source/BlockID.cpp @@ -778,10 +778,11 @@ public: g_BlockIsSolid[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE] = false; g_BlockIsSolid[E_BLOCK_MELON_STEM] = false; g_BlockIsSolid[E_BLOCK_NETHER_PORTAL] = false; - g_BlockIsSolid[E_BLOCK_PISTON_MOVED_BLOCK] = false; - g_BlockIsSolid[E_BLOCK_POTATOES] = false; - g_BlockIsSolid[E_BLOCK_PUMPKIN_STEM] = false; + g_BlockIsSolid[E_BLOCK_PISTON] = false; + g_BlockIsSolid[E_BLOCK_PISTON_EXTENSION] = false; g_BlockIsSolid[E_BLOCK_RAIL] = false; + g_BlockIsSolid[E_BLOCK_REDSTONE_REPEATER_OFF] = false; + g_BlockIsSolid[E_BLOCK_REDSTONE_REPEATER_ON] = false; g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_OFF] = false; g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_ON] = false; g_BlockIsSolid[E_BLOCK_REDSTONE_WIRE] = false; diff --git a/source/Blocks/BlockDropSpenser.h b/source/Blocks/BlockDropSpenser.h index e5572da8a..b7f20825d 100644 --- a/source/Blocks/BlockDropSpenser.h +++ b/source/Blocks/BlockDropSpenser.h @@ -31,7 +31,7 @@ public: a_BlockType = m_BlockType; // FIXME: Do not use cPiston class for dispenser placement! - a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0); + a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), a_Player->GetPitch()); return true; } } ; diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp index 451ad6b91..3e97d1e9d 100644 --- a/source/Blocks/BlockHandler.cpp +++ b/source/Blocks/BlockHandler.cpp @@ -354,6 +354,14 @@ void cBlockHandler::DropBlock(cWorld * a_World, cEntity * a_Digger, int a_BlockX if (!Pickups.empty()) { + // Add random offset to the spawn position: + // Commented out until bug with pickups not spawning properly is fixed, see World.cpp + /* + int MicroX = (int)(a_BlockX * 32) + (r1.randInt(16) + r1.randInt(16) - 16); + int MicroY = (int)(a_BlockY * 32) + (r1.randInt(16) + r1.randInt(16) - 16); + int MicroZ = (int)(a_BlockZ * 32) + (r1.randInt(16) + r1.randInt(16) - 16); + */ + a_World->SpawnItemPickups(Pickups, a_BlockX, a_BlockY, a_BlockZ); } } diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp index cb6799d33..d9272b39d 100644 --- a/source/Entities/Entity.cpp +++ b/source/Entities/Entity.cpp @@ -1,4 +1,3 @@ - #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Entity.h" @@ -13,6 +12,7 @@ #include "../Simulator/FluidSimulator.h" #include "../PluginManager.h" #include "../Tracer.h" +#include "Minecart.h" @@ -564,8 +564,43 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) else { // Push out entity. + BLOCKTYPE GotBlock; + + static const struct + { + int x, y, z; + } gCrossCoords[] = + { + { 1, 0, 0}, + {-1, 0, 0}, + { 0, 0, 1}, + { 0, 0, -1}, + } ; + + bool IsNoAirSurrounding = true; + for (int i = 0; i < ARRAYCOUNT(gCrossCoords); i++) + { + if (!NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock)) + { + // The pickup is too close to an unloaded chunk, bail out of any physics handling + return; + } + if (!g_BlockIsSolid[GotBlock]) + { + NextPos.x += gCrossCoords[i].x; + NextPos.z += gCrossCoords[i].z; + IsNoAirSurrounding = false; + break; + } + } // for i - gCrossCoords[] + + if (IsNoAirSurrounding) + { + NextPos.y += 0.5; + } + m_bOnGround = true; - NextPos.y += 0.2; + LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}", m_UniqueID, GetClass(), BlockX, BlockY, BlockZ ); @@ -578,6 +613,11 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) { fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water. } + else if ((IsBlockRail(BlockBelow)) && (IsMinecart())) // Rails aren't solid, except for Minecarts + { + fallspeed = 0; + m_bOnGround = true; + } else if (BlockIn == E_BLOCK_COBWEB) { NextSpeed.y *= 0.05; // Reduce overall falling speed @@ -592,27 +632,40 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) } else { - // TODO: This condition belongs to minecarts, without it, they derails too much. - // But it shouldn't be here for other entities. We need a complete minecart physics overhaul. - if ( - (BlockBelow != E_BLOCK_RAIL) && - (BlockBelow != E_BLOCK_DETECTOR_RAIL) && - (BlockBelow != E_BLOCK_POWERED_RAIL) && - (BlockBelow != E_BLOCK_ACTIVATOR_RAIL) - ) + if (IsMinecart()) { - // Friction - if (NextSpeed.SqrLength() > 0.0004f) + if (!IsBlockRail(BlockBelow)) { - NextSpeed.x *= 0.6666; - if (fabs(NextSpeed.x) < 0.05) + // Friction if minecart is off track, otherwise, Minecart.cpp handles this + if (NextSpeed.SqrLength() > 0.0004f) { - NextSpeed.x = 0; + NextSpeed.x *= 0.7f / (1 + a_Dt); + if (fabs(NextSpeed.x) < 0.05) + { + NextSpeed.x = 0; + } + NextSpeed.z *= 0.7f / (1 + a_Dt); + if (fabs(NextSpeed.z) < 0.05) + { + NextSpeed.z = 0; + } } - NextSpeed.z *= 0.6666; - if (fabs(NextSpeed.z) < 0.05) + } + else + { + // Friction + if (NextSpeed.SqrLength() > 0.0004f) { - NextSpeed.z = 0; + NextSpeed.x *= 0.7f / (1 + a_Dt); + if (fabs(NextSpeed.x) < 0.05) + { + NextSpeed.x = 0; + } + NextSpeed.z *= 0.7f / (1 + a_Dt); + if (fabs(NextSpeed.z) < 0.05) + { + NextSpeed.z = 0; + } } } } @@ -634,19 +687,19 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) switch(WaterDir) { case X_PLUS: - m_WaterSpeed.x = 1.f; + m_WaterSpeed.x = 0.2f; m_bOnGround = false; break; case X_MINUS: - m_WaterSpeed.x = -1.f; + m_WaterSpeed.x = -0.2f; m_bOnGround = false; break; case Z_PLUS: - m_WaterSpeed.z = 1.f; + m_WaterSpeed.z = 0.2f; m_bOnGround = false; break; case Z_MINUS: - m_WaterSpeed.z = -1.f; + m_WaterSpeed.z = -0.2f; m_bOnGround = false; break; @@ -677,7 +730,6 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) { if( Ret == 1 ) { - if( Tracer.HitNormal.x != 0.f ) NextSpeed.x = 0.f; if( Tracer.HitNormal.y != 0.f ) NextSpeed.y = 0.f; if( Tracer.HitNormal.z != 0.f ) NextSpeed.z = 0.f; @@ -688,11 +740,14 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) } } NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z); - NextPos.x += Tracer.HitNormal.x * 0.5f; - NextPos.z += Tracer.HitNormal.z * 0.5f; + NextPos.x += Tracer.HitNormal.x * 0.3f; + NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot + NextPos.z += Tracer.HitNormal.z * 0.3f; } else + { NextPos += (NextSpeed * a_Dt); + } } else { diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp index 0c0b7b58a..a2f1e5593 100644 --- a/source/Entities/Minecart.cpp +++ b/source/Entities/Minecart.cpp @@ -54,20 +54,24 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) if ((GetPosY() > 0) && (GetPosY() < cChunkDef::Height)) { BLOCKTYPE BelowType = GetWorld()->GetBlock(floor(GetPosX()), floor(GetPosY() -1 ), floor(GetPosZ())); + BLOCKTYPE InsideType = GetWorld()->GetBlock(floor(GetPosX()), floor(GetPosY()), floor(GetPosZ())); - if ( - (BelowType == E_BLOCK_RAIL) || - (BelowType == E_BLOCK_POWERED_RAIL) || - (BelowType == E_BLOCK_DETECTOR_RAIL) || - (BelowType == E_BLOCK_ACTIVATOR_RAIL) - ) + if (IsBlockRail(BelowType)) { HandleRailPhysics(a_Dt, a_Chunk); } else { - super::HandlePhysics(a_Dt, a_Chunk); - BroadcastMovementUpdate(); + if (IsBlockRail(InsideType)) + { + SetPosY(ceil(GetPosY())); + HandleRailPhysics(a_Dt, a_Chunk); + } + else + { + super::HandlePhysics(a_Dt, a_Chunk); + BroadcastMovementUpdate(); + } } } else @@ -105,9 +109,6 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) SpeedY = 0; // Don't move vertically as on ground SpeedX = 0; // Correct diagonal movement from curved rails - // Set Y as current Y rounded up to bypass friction - SetPosY(floor(GetPosY())); - if (SpeedZ != 0) // Don't do anything if cart is stationary { if (SpeedZ > 0) @@ -130,8 +131,6 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) SpeedY = 0; SpeedZ = 0; - SetPosY(floor(GetPosY())); - if (SpeedX != 0) { if (SpeedX > 0) @@ -347,7 +346,7 @@ void cMinecart::DoTakeDamage(TakeDamageInfo & TDI) { super::DoTakeDamage(TDI); - if (GetHealth() == 0) + if (GetHealth() <= 0) { Destroy(true); } diff --git a/source/Entities/Minecart.h b/source/Entities/Minecart.h index f98b02bb5..0ca6586db 100644 --- a/source/Entities/Minecart.h +++ b/source/Entities/Minecart.h @@ -16,6 +16,20 @@ +inline bool IsBlockRail(BLOCKTYPE a_BlockType) + { + return ( + (a_BlockType == E_BLOCK_RAIL) || + (a_BlockType == E_BLOCK_ACTIVATOR_RAIL) || + (a_BlockType == E_BLOCK_DETECTOR_RAIL) || + (a_BlockType == E_BLOCK_POWERED_RAIL) + ) ; + } + + + + + class cMinecart : public cEntity { diff --git a/source/Entities/Pickup.cpp b/source/Entities/Pickup.cpp index 9b388366a..db7be8b04 100644 --- a/source/Entities/Pickup.cpp +++ b/source/Entities/Pickup.cpp @@ -25,7 +25,7 @@ cPickup::cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem & a_Item, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */) - : cEntity(etPickup, ((double)(a_MicroPosX)) / 32, ((double)(a_MicroPosY)) / 32, ((double)(a_MicroPosZ)) / 32, 0.2, 0.2) + : cEntity(etPickup, (((double)(a_MicroPosX)) / 32) + 0.1 /*Accomodate player vomiting*/, ((double)(a_MicroPosY)) / 32, ((double)(a_MicroPosZ)) / 32, 0.2, 0.2) , m_Timer( 0.f ) , m_Item(a_Item) , m_bCollected( false ) @@ -33,7 +33,6 @@ cPickup::cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem m_MaxHealth = 5; m_Health = 5; SetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ); - m_Gravity = -3.0; } diff --git a/source/Entities/Player.cpp b/source/Entities/Player.cpp index 751920759..04d285b01 100644 --- a/source/Entities/Player.cpp +++ b/source/Entities/Player.cpp @@ -1184,7 +1184,7 @@ void cPlayer::TossItem( double vX = 0, vY = 0, vZ = 0; EulerToVector(-GetRotation(), GetPitch(), vZ, vX, vY); vY = -vY * 2 + 1.f; - m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY() + 1.6f, GetPosZ(), vX * 2, vY * 2, vZ * 2); + m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY() + 1.6f, GetPosZ(), vX * 3, vY * 3, vZ * 3); } diff --git a/source/Items/ItemShears.h b/source/Items/ItemShears.h index 663fa0170..6a17607ee 100644 --- a/source/Items/ItemShears.h +++ b/source/Items/ItemShears.h @@ -38,7 +38,6 @@ public: a_Player->UseEquippedItem(); return true; } - // TODO: cobweb, vines return false; } diff --git a/source/Simulator/SandSimulator.cpp b/source/Simulator/SandSimulator.cpp index f4f0cdc80..87fb83357 100644 --- a/source/Simulator/SandSimulator.cpp +++ b/source/Simulator/SandSimulator.cpp @@ -258,7 +258,7 @@ void cSandSimulator::FinishFalling( // Create a pickup instead: cItems Pickups; Pickups.Add((ENUM_ITEM_ID)a_FallingBlockType, 1, a_FallingBlockMeta); - a_World->SpawnItemPickups(Pickups, (double)a_BlockX + 0.5, (double)a_BlockY + 0.5, (double)a_BlockZ + 0.5, 0); + a_World->SpawnItemPickups(Pickups, (double)a_BlockX + 0.5, (double)a_BlockY + 0.5, (double)a_BlockZ + 0.5); } diff --git a/source/UI/SlotArea.cpp b/source/UI/SlotArea.cpp index 9213d4ff8..0a37e82b0 100644 --- a/source/UI/SlotArea.cpp +++ b/source/UI/SlotArea.cpp @@ -793,7 +793,7 @@ void cSlotAreaTemporary::TossItems(cPlayer & a_Player, int a_Begin, int a_End) double vX = 0, vY = 0, vZ = 0; EulerToVector(-a_Player.GetRotation(), a_Player.GetPitch(), vZ, vX, vY); vY = -vY * 2 + 1.f; - a_Player.GetWorld()->SpawnItemPickups(Drops, a_Player.GetPosX(), a_Player.GetPosY() + 1.6f, a_Player.GetPosZ(), vX * 2, vY * 2, vZ * 2); + a_Player.GetWorld()->SpawnItemPickups(Drops, a_Player.GetPosX(), a_Player.GetPosY() + 1.6f, a_Player.GetPosZ(), vX * 3, vY * 3, vZ * 3); } diff --git a/source/World.cpp b/source/World.cpp index edcbb48f2..882cf90d2 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -1514,22 +1514,13 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr) { float SpeedX = (float)(a_FlyAwaySpeed * (r1.randInt(1000) - 500)); - float SpeedY = (float)(a_FlyAwaySpeed * r1.randInt(1000)); + float SpeedY = 1; float SpeedZ = (float)(a_FlyAwaySpeed * (r1.randInt(1000) - 500)); - - // Add random offset to the spawn position: - int MicroX = (int)(a_BlockX * 32) + (r1.randInt(16) + r1.randInt(16) - 16); - int MicroY = (int)(a_BlockY * 32) + (r1.randInt(16) + r1.randInt(16) - 16); - int MicroZ = (int)(a_BlockZ * 32) + (r1.randInt(16) + r1.randInt(16) - 16); - // TODO 2013_05_12 _X: Because spawning pickups with nonzero speed causes them to bug (FS #338), - // I decided to temporarily reset the speed to zero to fix it, until we have proper pickup physics - SpeedX = SpeedY = SpeedZ = 0; - - // TODO 2013_05_12 _X: It seems that pickups bug out even with zero speed, trying mid-block position: - MicroX = (int)(floor(a_BlockX) * 32) + 16; - MicroY = (int)(floor(a_BlockY) * 32) + 16; - MicroZ = (int)(floor(a_BlockZ) * 32) + 16; + // Pickup doesn't spawn on client without a mid block position. Perhaps the doubles are causing issues? + int MicroX = (int)(floor(a_BlockX) * 32) + 16; + int MicroY = (int)(floor(a_BlockY) * 32) + 16; + int MicroZ = (int)(floor(a_BlockZ) * 32) + 16; cPickup * Pickup = new cPickup( MicroX, MicroY, MicroZ, @@ -1545,23 +1536,14 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ) { - // TODO 2013_05_12 _X: Because spawning pickups with nonzero speed causes them to bug (FS #338), - // I decided to temporarily reset the speed to zero to fix it, until we have proper pickup physics - a_SpeedX = a_SpeedY = a_SpeedZ = 0; - MTRand r1; for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr) { - // Add random offset to the spawn position: - int MicroX = (int)(a_BlockX * 32) + (r1.randInt(16) + r1.randInt(16) - 16); - int MicroY = (int)(a_BlockY * 32) + (r1.randInt(16) + r1.randInt(16) - 16); - int MicroZ = (int)(a_BlockZ * 32) + (r1.randInt(16) + r1.randInt(16) - 16); - - // TODO 2013_05_12 _X: It seems that pickups bug out even with zero speed, trying mid-block position: - MicroX = (int)(floor(a_BlockX) * 32) + 16; - MicroY = (int)(floor(a_BlockY) * 32) + 16; - MicroZ = (int)(floor(a_BlockZ) * 32) + 16; - + // Pickup doesn't spawn on client without a mid block position. Perhaps the doubles are causing issues? + int MicroX = (int)(floor(a_BlockX) * 32) + 16; + int MicroY = (int)(floor(a_BlockY) * 32) + 16; + int MicroZ = (int)(floor(a_BlockZ) * 32) + 16; + cPickup * Pickup = new cPickup( MicroX, MicroY, MicroZ, *itr, (float)a_SpeedX, (float)a_SpeedY, (float)a_SpeedZ