diff options
Diffstat (limited to 'source/Entities')
-rw-r--r-- | source/Entities/Boat.cpp | 87 | ||||
-rw-r--r-- | source/Entities/Boat.h | 37 | ||||
-rw-r--r-- | source/Entities/Entity.cpp | 132 | ||||
-rw-r--r-- | source/Entities/Entity.h | 79 | ||||
-rw-r--r-- | source/Entities/Minecart.cpp | 116 | ||||
-rw-r--r-- | source/Entities/Minecart.h | 28 | ||||
-rw-r--r-- | source/Entities/Pickup.cpp | 5 | ||||
-rw-r--r-- | source/Entities/Pickup.h | 2 | ||||
-rw-r--r-- | source/Entities/Player.cpp | 27 |
9 files changed, 415 insertions, 98 deletions
diff --git a/source/Entities/Boat.cpp b/source/Entities/Boat.cpp new file mode 100644 index 000000000..56e766dd4 --- /dev/null +++ b/source/Entities/Boat.cpp @@ -0,0 +1,87 @@ + +// Boat.cpp + +// Implements the cBoat class representing a boat in the world + +#include "Globals.h" +#include "Boat.h" +#include "../World.h" +#include "../ClientHandle.h" +#include "Player.h" + + + + + +cBoat::cBoat(double a_X, double a_Y, double a_Z) : + super(etBoat, a_X, a_Y, a_Z, 0.98, 0.7) +{ + SetMass(20.f); + SetMaxHealth(6); + SetHealth(6); +} + + + + +void cBoat::SpawnOn(cClientHandle & a_ClientHandle) +{ + a_ClientHandle.SendSpawnVehicle(*this, 1); +} + + + + + +void cBoat::DoTakeDamage(TakeDamageInfo & TDI) +{ + super::DoTakeDamage(TDI); + + if (GetHealth() == 0) + { + Destroy(true); + } +} + + + + + +void cBoat::OnRightClicked(cPlayer & a_Player) +{ + if (m_Attachee != NULL) + { + if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) + { + // This player is already sitting in, they want out. + a_Player.Detach(); + return; + } + + if (m_Attachee->IsPlayer()) + { + // Another player is already sitting in here, cannot attach + return; + } + + // Detach whatever is sitting in this boat now: + m_Attachee->Detach(); + } + + // Attach the player to this boat + a_Player.AttachTo(this); +} + + + + + +void cBoat::HandlePhysics(float a_Dt, cChunk & a_Chunk) +{ + super::HandlePhysics(a_Dt, a_Chunk); + BroadcastMovementUpdate(); +} + + + + diff --git a/source/Entities/Boat.h b/source/Entities/Boat.h new file mode 100644 index 000000000..8c51ab86c --- /dev/null +++ b/source/Entities/Boat.h @@ -0,0 +1,37 @@ + +// Boat.h + +// Declares the cBoat class representing a boat in the world + + + + + +#pragma once + +#include "Entity.h" + + + + + +class cBoat : + public cEntity +{ + typedef cEntity super; + +public: + CLASS_PROTODEF(cBoat); + + // cEntity overrides: + virtual void SpawnOn(cClientHandle & a_ClientHandle) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void DoTakeDamage(TakeDamageInfo & TDI) override; + virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override; + + cBoat(double a_X, double a_Y, double a_Z); +} ; + + + + diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp index 1a593b3d1..d465c75bd 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" @@ -55,6 +55,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d , m_TicksSinceLastBurnDamage(0) , m_TicksSinceLastLavaDamage(0) , m_TicksSinceLastFireDamage(0) + , m_TicksSinceLastVoidDamage(0) , m_TicksLeftBurning(0) , m_WaterSpeed(0, 0, 0) , m_Width(a_Width) @@ -505,6 +506,11 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) { TickBurning(a_Chunk); } + if ((a_Chunk.IsValid()) && (GetPosY() < -46)) + { + TickInVoid(a_Chunk); + } + else { m_TicksSinceLastVoidDamage = 0; } } @@ -524,8 +530,15 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) if ((BlockY >= cChunkDef::Height) || (BlockY < 0)) { // Outside of the world - // TODO: Current speed should still be added to the entity position - // Otherwise TNT explosions in the void will still effect the bottommost layers of the world + + cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ); + // See if we can commit our changes. If not, we will discard them. + if (NextChunk != NULL) + { + SetSpeed(NextSpeed); + NextPos += (NextSpeed * a_Dt); + SetPosition(NextPos); + } return; } @@ -536,12 +549,11 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width); int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width); BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ ); - BLOCKTYPE BlockBelow = NextChunk->GetBlock( RelBlockX, BlockY - 1, RelBlockZ ); + BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR; if (!g_BlockIsSolid[BlockIn]) // Making sure we are not inside a solid block { if (m_bOnGround) // check if it's still on the ground { - BLOCKTYPE BlockBelow = NextChunk->GetBlock( RelBlockX, BlockY - 1, RelBlockZ ); if (!g_BlockIsSolid[BlockBelow]) // Check if block below is air or water. { m_bOnGround = false; @@ -551,8 +563,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 ); @@ -565,6 +612,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 @@ -579,24 +631,37 @@ 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 (!IsBlockRail(BlockBelow)) + { + // Friction if minecart is off track, otherwise, Minecart.cpp handles this + if (NextSpeed.SqrLength() > 0.0004f) + { + 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; + } + } + } + } + else + { + // Friction for non-minecarts if (NextSpeed.SqrLength() > 0.0004f) { - NextSpeed.x *= 0.6666; + NextSpeed.x *= 0.7f / (1 + a_Dt); if (fabs(NextSpeed.x) < 0.05) { NextSpeed.x = 0; } - NextSpeed.z *= 0.6666; + NextSpeed.z *= 0.7f / (1 + a_Dt); if (fabs(NextSpeed.z) < 0.05) { NextSpeed.z = 0; @@ -621,19 +686,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; @@ -664,7 +729,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; @@ -675,11 +739,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 { @@ -829,6 +896,23 @@ void cEntity::TickBurning(cChunk & a_Chunk) +void cEntity::TickInVoid(cChunk & a_Chunk) +{ + if (m_TicksSinceLastVoidDamage == 20) + { + TakeDamage(dtInVoid, NULL, 2, 0); + m_TicksSinceLastVoidDamage = 0; + } + else + { + m_TicksSinceLastVoidDamage++; + } +} + + + + + /// Called when the entity starts burning void cEntity::OnStartedBurning(void) { diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h index b063838eb..c6b70a7fc 100644 --- a/source/Entities/Entity.h +++ b/source/Entities/Entity.h @@ -61,7 +61,26 @@ struct TakeDamageInfo // tolua_begin class cEntity { -public: +public: + + enum eEntityType + { + etEntity, // For all other types + etPlayer, + etPickup, + etMonster, + etFallingBlock, + etMinecart, + etBoat, + etTNT, + etProjectile, + + // Common variations + etMob = etMonster, // DEPRECATED, use etMonster instead! + } ; + + // tolua_end + enum { ENTITY_STATUS_HURT = 2, @@ -71,6 +90,13 @@ public: ENTITY_STATUS_WOLF_SHAKING = 8, ENTITY_STATUS_EATING_ACCEPTED = 9, ENTITY_STATUS_SHEEP_EATING = 10, + ENTITY_STATUS_GOLEM_ROSING = 11, + ENTITY_STATUS_VILLAGER_HEARTS = 12, + ENTITY_STATUS_VILLAGER_ANGRY = 13, + ENTITY_STATUS_VILLAGER_HAPPY = 14, + ENTITY_STATUS_WITCH_MAGICKING = 15, + // It seems 16 (zombie conversion) is now done with metadata + ENTITY_STATUS_FIREWORK_EXPLODE= 17, } ; enum @@ -84,27 +110,6 @@ public: BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire } ; - enum eEntityType - { - etEntity, // For all other types - etPlayer, - etPickup, - etMonster, - etFallingBlock, - etMinecart, - etTNT, - etProjectile, - - // DEPRECATED older constants, left over for compatibility reasons (plugins) - etMob = etMonster, // DEPRECATED, use etMonster instead! - eEntityType_Entity = etEntity, - eEntityType_Player = etPlayer, - eEntityType_Pickup = etPickup, - eEntityType_Mob = etMob, - } ; - - // tolua_end - cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); virtual ~cEntity(); @@ -115,11 +120,14 @@ public: eEntityType GetEntityType(void) const { return m_EntityType; } - bool IsPlayer (void) const { return (m_EntityType == etPlayer); } - bool IsPickup (void) const { return (m_EntityType == etPickup); } - bool IsMob (void) const { return (m_EntityType == etMob); } - bool IsMinecart(void) const { return (m_EntityType == etMinecart); } - bool IsTNT (void) const { return (m_EntityType == etTNT); } + bool IsPlayer (void) const { return (m_EntityType == etPlayer); } + bool IsPickup (void) const { return (m_EntityType == etPickup); } + bool IsMob (void) const { return (m_EntityType == etMonster); } + bool IsFallingBlock(void) const { return (m_EntityType == etFallingBlock); } + bool IsMinecart (void) const { return (m_EntityType == etMinecart); } + bool IsBoat (void) const { return (m_EntityType == etBoat); } + bool IsTNT (void) const { return (m_EntityType == etTNT); } + bool IsProjectile (void) const { return (m_EntityType == etProjectile); } /// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true) virtual bool IsA(const char * a_ClassName) const; @@ -232,16 +240,16 @@ public: /// Returns the curently equipped weapon; empty item if none virtual cItem GetEquippedWeapon(void) const { return cItem(); } - /// Returns the currently equipped helmet; empty item if nonte + /// Returns the currently equipped helmet; empty item if none virtual cItem GetEquippedHelmet(void) const { return cItem(); } - /// Returns the currently equipped chestplate; empty item if nonte + /// Returns the currently equipped chestplate; empty item if none virtual cItem GetEquippedChestplate(void) const { return cItem(); } - /// Returns the currently equipped leggings; empty item if nonte + /// Returns the currently equipped leggings; empty item if none virtual cItem GetEquippedLeggings(void) const { return cItem(); } - /// Returns the currently equipped boots; empty item if nonte + /// Returns the currently equipped boots; empty item if none virtual cItem GetEquippedBoots(void) const { return cItem(); } /// Called when the health drops below zero. a_Killer may be NULL (environmental damage) @@ -265,6 +273,9 @@ public: /// Updates the state related to this entity being on fire virtual void TickBurning(cChunk & a_Chunk); + + /// Handles when the entity is in the void + virtual void TickInVoid(cChunk & a_Chunk); /// Called when the entity starts burning virtual void OnStartedBurning(void); @@ -322,12 +333,13 @@ public: // tolua_begin - // Metadata flags; descendants may override the defaults: + // COMMON metadata flags; descendants may override the defaults: virtual bool IsOnFire (void) const {return (m_TicksLeftBurning > 0); } virtual bool IsCrouched (void) const {return false; } virtual bool IsRiding (void) const {return false; } virtual bool IsSprinting(void) const {return false; } virtual bool IsRclking (void) const {return false; } + virtual bool IsInvisible(void) const {return false; } // tolua_end @@ -387,6 +399,9 @@ protected: /// Time, in ticks, until the entity extinguishes its fire int m_TicksLeftBurning; + + /// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void. + int m_TicksSinceLastVoidDamage; virtual void Destroyed(void) {} // Called after the entity has been destroyed diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp index 0c0b7b58a..f75e23d8b 100644 --- a/source/Entities/Minecart.cpp +++ b/source/Entities/Minecart.cpp @@ -8,6 +8,7 @@ #include "Minecart.h" #include "../World.h" #include "../ClientHandle.h" +#include "../Chunk.h" #include "Player.h" @@ -16,7 +17,8 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) : super(etMinecart, a_X, a_Y, a_Z, 0.98, 0.7), - m_Payload(a_Payload) + m_Payload(a_Payload), + m_LastDamage(0) { SetMass(20.f); SetMaxHealth(6); @@ -51,30 +53,43 @@ void cMinecart::SpawnOn(cClientHandle & a_ClientHandle) void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) { - if ((GetPosY() > 0) && (GetPosY() < cChunkDef::Height)) + int PosY = (int)floor(GetPosY()); + if ((PosY <= 0) || (PosY >= cChunkDef::Height)) { - BLOCKTYPE BelowType = GetWorld()->GetBlock(floor(GetPosX()), floor(GetPosY() -1 ), floor(GetPosZ())); - - if ( - (BelowType == E_BLOCK_RAIL) || - (BelowType == E_BLOCK_POWERED_RAIL) || - (BelowType == E_BLOCK_DETECTOR_RAIL) || - (BelowType == E_BLOCK_ACTIVATOR_RAIL) - ) + // Outside the world, just process normal falling physics + super::HandlePhysics(a_Dt, a_Chunk); + BroadcastMovementUpdate(); + return; + } + + int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width; + cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ); + if (Chunk == NULL) + { + // Inside an unloaded chunk, bail out all processing + return; + } + BLOCKTYPE BelowType = Chunk->GetBlock(RelPosX, PosY - 1, RelPosZ); + BLOCKTYPE InsideType = Chunk->GetBlock(RelPosX, PosY, RelPosZ); + + if (IsBlockRail(BelowType)) + { + HandleRailPhysics(a_Dt, *Chunk); + } + else + { + if (IsBlockRail(InsideType)) { - HandleRailPhysics(a_Dt, a_Chunk); + SetPosY(PosY + 1); + HandleRailPhysics(a_Dt, *Chunk); } else { - super::HandlePhysics(a_Dt, a_Chunk); + super::HandlePhysics(a_Dt, *Chunk); BroadcastMovementUpdate(); } } - else - { - super::HandlePhysics(a_Dt, a_Chunk); - BroadcastMovementUpdate(); - } } @@ -83,6 +98,7 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) static const double MAX_SPEED = 8; static const double MAX_SPEED_NEGATIVE = (0 - MAX_SPEED); + void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) { @@ -94,7 +110,9 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) */ // Get block meta below the cart - NIBBLETYPE BelowMeta = GetWorld()->GetBlockMeta(floor(GetPosX()), floor(GetPosY() -1 ), floor(GetPosZ())); + int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width; + NIBBLETYPE BelowMeta = a_Chunk.GetMeta(RelPosX, (int)floor(GetPosY() - 1), RelPosZ); double SpeedX = GetSpeedX(), SpeedY = GetSpeedY(), SpeedZ = GetSpeedZ(); // Get current speed switch (BelowMeta) @@ -105,9 +123,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 +145,6 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) SpeedY = 0; SpeedZ = 0; - SetPosY(floor(GetPosY())); - if (SpeedX != 0) { if (SpeedX > 0) @@ -345,11 +358,51 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) void cMinecart::DoTakeDamage(TakeDamageInfo & TDI) { + m_LastDamage = TDI.FinalDamage; super::DoTakeDamage(TDI); - if (GetHealth() == 0) + m_World->BroadcastEntityMetadata(*this); + + if (GetHealth() <= 0) { Destroy(true); + + cItems Drops; + switch (m_Payload) + { + case mpNone: + { + Drops.push_back(cItem(E_ITEM_MINECART, 1, 0)); + break; + } + case mpChest: + { + Drops.push_back(cItem(E_ITEM_CHEST_MINECART, 1, 0)); + break; + } + case mpFurnace: + { + Drops.push_back(cItem(E_ITEM_FURNACE_MINECART, 1, 0)); + break; + } + case mpTNT: + { + Drops.push_back(cItem(E_ITEM_MINECART_WITH_TNT, 1, 0)); + break; + } + case mpHopper: + { + Drops.push_back(cItem(E_ITEM_MINECART_WITH_HOPPER, 1, 0)); + break; + } + default: + { + ASSERT(!"Unhandled minecart type when spawning pickup!"); + return; + } + } + + m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ()); } } @@ -435,7 +488,8 @@ void cMinecartWithChest::OnRightClicked(cPlayer & a_Player) // cMinecartWithFurnace: cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) : - super(mpFurnace, a_X, a_Y, a_Z) + super(mpFurnace, a_X, a_Y, a_Z), + m_IsFueled(false) { } @@ -445,8 +499,16 @@ cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) : void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player) { - // Try to power the furnace with whatever the player is holding - // TODO + if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_COAL) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + + m_IsFueled = true; + m_World->BroadcastEntityMetadata(*this); + } } diff --git a/source/Entities/Minecart.h b/source/Entities/Minecart.h index f98b02bb5..b1b48be4e 100644 --- a/source/Entities/Minecart.h +++ b/source/Entities/Minecart.h @@ -10,7 +10,20 @@ #pragma once #include "Entity.h" -#include "../Item.h" + + + + + +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) + ) ; + } @@ -37,16 +50,19 @@ public: // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override; - void HandleRailPhysics(float a_Dt, cChunk & a_Chunk); virtual void DoTakeDamage(TakeDamageInfo & TDI) override; - + int LastDamage(void) const { return m_LastDamage; } + void HandleRailPhysics(float a_Dt, cChunk & a_Chunk); ePayload GetPayload(void) const { return m_Payload; } protected: ePayload m_Payload; cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z); + + int m_LastDamage; + } ; @@ -114,6 +130,12 @@ public: // cEntity overrides: virtual void OnRightClicked(cPlayer & a_Player) override; + bool IsFueled (void) const { return m_IsFueled; } + +private: + + bool m_IsFueled; + } ; diff --git a/source/Entities/Pickup.cpp b/source/Entities/Pickup.cpp index 9b388366a..075f93449 100644 --- a/source/Entities/Pickup.cpp +++ b/source/Entities/Pickup.cpp @@ -24,8 +24,8 @@ -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) +cPickup::cPickup(double a_X, double a_Y, double a_Z, const cItem & a_Item, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */) + : cEntity(etPickup, a_X, a_Y, a_Z, 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/Pickup.h b/source/Entities/Pickup.h index af6eaf3bb..488f91fb2 100644 --- a/source/Entities/Pickup.h +++ b/source/Entities/Pickup.h @@ -24,7 +24,7 @@ class cPickup : public: CLASS_PROTODEF(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); // tolua_export + cPickup(double a_X, double a_Y, double a_Z, const cItem & a_Item, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f); // tolua_export cItem & GetItem(void) {return m_Item; } // tolua_export const cItem & GetItem(void) const {return m_Item; } diff --git a/source/Entities/Player.cpp b/source/Entities/Player.cpp index 0943f61ff..d93b45614 100644 --- a/source/Entities/Player.cpp +++ b/source/Entities/Player.cpp @@ -16,7 +16,6 @@ #include "../Item.h" #include "../Tracer.h" #include "../Root.h" -#include "../OSSupport/MakeDir.h" #include "../OSSupport/Timer.h" #include "../MersenneTwister.h" #include "../Chunk.h" @@ -220,7 +219,6 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) if (m_IsChargingBow) { m_BowCharge += 1; - LOGD("Player \"%s\" charging bow: %d", m_PlayerName.c_str(), m_BowCharge); } if (m_bDirtyPosition) @@ -611,10 +609,13 @@ void cPlayer::SetSprint(bool a_IsSprinting) void cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI) { - if (m_GameMode == eGameMode_Creative) + if (a_TDI.DamageType != dtInVoid) { - // No damage / health in creative mode - return; + if (IsGameModeCreative()) + { + // No damage / health in creative mode + return; + } } super::DoTakeDamage(a_TDI); @@ -1182,7 +1183,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); } @@ -1338,7 +1339,7 @@ bool cPlayer::LoadFromDisk() bool cPlayer::SaveToDisk() { - cMakeDir::MakeDir("players"); + cFile::CreateFolder(FILE_IO_PREFIX + AString("players")); // create the JSON data Json::Value JSON_PlayerPosition; @@ -1446,7 +1447,17 @@ void cPlayer::SetSwimState(cChunk & a_Chunk) // Check if the player is swimming: // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk - VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn)); + if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn)) + { + // This sometimes happens on Linux machines + // Ref.: http://forum.mc-server.org/showthread.php?tid=1244 + LOGD("SetSwimState failure: RelX = %d, RelZ = %d, LastPos = {%.02f, %.02f}, Pos = %.02f, %.02f}", + RelX, RelY, m_LastPosX, m_LastPosZ, GetPosX(), GetPosZ() + ); + m_IsSwimming = false; + m_IsSubmerged = false; + return; + } m_IsSwimming = IsBlockWater(BlockIn); // Check if the player is submerged: |