From ddd03a050bfaaffef9abd573fe6c8e1af3948048 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 18 Jan 2014 20:58:26 +0000 Subject: Minecart collision and general improvements + Implemented collision on one type of rail * Improved curved rails somewhat * Fixed a crash bug --- src/Entities/Minecart.cpp | 305 +++++++++++++++++++++++++++++++++++----------- src/Entities/Minecart.h | 7 +- 2 files changed, 242 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 7f3fea5ec..ad63f848e 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -19,6 +19,70 @@ +class cMinecartCollisionCallback : + public cEntityCallback +{ +public: + cMinecartCollisionCallback(Vector3d a_Pos, double a_Height, double a_Width, int a_UniqueID, int a_AttacheeUniqueID) : + m_Pos(a_Pos), + m_Height(a_Height), + m_Width(a_Width), + m_DoesInteserct(false), + m_CollidedEntityPos(0, 0, 0), + m_UniqueID(a_UniqueID), + m_AttacheeUniqueID(a_AttacheeUniqueID) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + ASSERT(a_Entity != NULL); + + if (!a_Entity->IsPlayer() && !a_Entity->IsMob() && !a_Entity->IsMinecart() && !a_Entity->IsBoat()) + { + return false; + } + else if ((a_Entity->GetUniqueID() == m_UniqueID) || (a_Entity->GetUniqueID() == m_AttacheeUniqueID)) + { + return false; + } + + cBoundingBox bbEntity(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight()); + cBoundingBox bbMinecart(Vector3d(m_Pos.x, floor(m_Pos.y), m_Pos.z), m_Width / 2, m_Height); + + if (bbEntity.DoesIntersect(bbMinecart)) + { + m_CollidedEntityPos = a_Entity->GetPosition(); + m_DoesInteserct = true; + return true; + } + return false; + } + + bool FoundIntersection(void) const + { + return m_DoesInteserct; + } + + Vector3d GetCollidedEntityPosition(void) const + { + return m_CollidedEntityPos; + } + +protected: + bool m_DoesInteserct; + + Vector3d m_CollidedEntityPos; + + Vector3d m_Pos; + double m_Height, m_Width; + int m_UniqueID; + int m_AttacheeUniqueID; +}; + + + + 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), @@ -30,7 +94,7 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) : SetMass(20.f); SetMaxHealth(6); SetHealth(6); - SetWidth(1.2); + SetWidth(1); SetHeight(0.9); } @@ -153,7 +217,9 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) SetSpeedY(0); // Don't move vertically as on ground SetSpeedX(0); // Correct diagonal movement from curved rails - if (TestBlockCollision(a_RailMeta)) return; + // Execute both the entity and block collision checks + bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); + if (EntCol || BlckCol) return; if (GetSpeedZ() != 0) // Don't do anything if cart is stationary { @@ -177,7 +243,8 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) SetSpeedY(0); SetSpeedZ(0); - if (TestBlockCollision(a_RailMeta)) return; + bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); + if (EntCol || BlckCol) return; if (GetSpeedX() != 0) { @@ -281,24 +348,11 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) SetRotation(315); // Set correct rotation server side SetPosY(floor(GetPosY()) + 0.55); // Levitate dat cart - if (TestBlockCollision(a_RailMeta)) return; + TestBlockCollision(a_RailMeta); + TestEntityCollision(a_RailMeta); + + // SnapToRail handles turning - if (GetSpeedZ() > 0) // Cart moving south - { - int OldX = (int)floor(GetPosX()); - AddSpeedX(-GetSpeedZ() + 0.5); // See below - AddPosX(-GetSpeedZ() * (a_Dt / 1000)); // Diagonally move southwest (which will make cart hit a southwest rail) - // If we are already at southwest rail, set Z speed to zero as we can be moving so fast, MCS doesn't tick fast enough to active the handle for the rail... - // ...and so we derail unexpectedly. - if (GetPosX() <= OldX - 1) SetSpeedZ(0); - } - else if (GetSpeedX() > 0) // Cart moving east - { - int OldZ = (int)floor(GetPosZ()); - AddSpeedZ(-GetSpeedX() + 0.5); - AddPosZ(-GetSpeedX() * (a_Dt / 1000)); // Diagonally move northeast - if (GetPosZ() <= OldZ - 1) SetSpeedX(0); - } break; } case E_META_RAIL_CURVED_ZM_XP: // Curved NORTH EAST @@ -306,22 +360,9 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) SetRotation(225); SetPosY(floor(GetPosY()) + 0.55); - if (TestBlockCollision(a_RailMeta)) return; + TestBlockCollision(a_RailMeta); + TestEntityCollision(a_RailMeta); - if (GetSpeedZ() > 0) - { - int OldX = (int)floor(GetPosX()); - AddSpeedX(GetSpeedZ() - 0.5); - AddPosX(GetSpeedZ() * (a_Dt / 1000)); - if (GetPosX() >= OldX + 1) SetSpeedZ(0); - } - else if (GetSpeedX() < 0) - { - int OldZ = (int)floor(GetPosZ()); - AddSpeedZ(GetSpeedX() + 0.5); - AddPosZ(GetSpeedX() * (a_Dt / 1000)); - if (GetPosZ() <= OldZ - 1) SetSpeedX(0); - } break; } case E_META_RAIL_CURVED_ZP_XM: // Curved SOUTH WEST @@ -329,22 +370,9 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) SetRotation(135); SetPosY(floor(GetPosY()) + 0.55); - if (TestBlockCollision(a_RailMeta)) return; + TestBlockCollision(a_RailMeta); + TestEntityCollision(a_RailMeta); - if (GetSpeedZ() < 0) - { - int OldX = (int)floor(GetPosX()); - AddSpeedX(GetSpeedZ() + 0.5); - AddPosX(GetSpeedZ() * (a_Dt / 1000)); - if (GetPosX() <= OldX - 1) SetSpeedZ(0); - } - else if (GetSpeedX() > 0) - { - int OldZ = (int)floor(GetPosZ()); - AddSpeedZ(GetSpeedX() - 0.5); - AddPosZ(GetSpeedX() * (a_Dt / 1000)); - if (GetPosZ() >= OldZ + 1) SetSpeedX(0); - } break; } case E_META_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST @@ -352,22 +380,9 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) SetRotation(45); SetPosY(floor(GetPosY()) + 0.55); - if (TestBlockCollision(a_RailMeta)) return; + TestBlockCollision(a_RailMeta); + TestEntityCollision(a_RailMeta); - if (GetSpeedZ() < 0) - { - int OldX = (int)floor(GetPosX()); - AddSpeedX(-GetSpeedZ() - 0.5); - AddPosX(-GetSpeedZ() * (a_Dt / 1000)); - if (GetPosX() >= OldX + 1) SetSpeedZ(0); - } - else if (GetSpeedX() < 0) - { - int OldZ = (int)floor(GetPosZ()); - AddSpeedZ(-GetSpeedX() - 0.5); - AddPosZ(-GetSpeedX() * (a_Dt / 1000)); - if (GetPosZ() >= OldZ + 1) SetSpeedX(0); - } break; } default: @@ -481,6 +496,102 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetPosX(floor(GetPosX()) + 0.5); break; } + case E_META_RAIL_CURVED_ZM_XM: + { + if (GetPosZ() < floor(GetPosZ()) + 0.5) + { + if (GetSpeedX() > 0) + { + SetSpeedZ(-GetSpeedX() * 0.7); + } + + SetSpeedX(0); + SetPosX(floor(GetPosX()) + 0.5); + } + else + { + if (GetSpeedZ() > 0) + { + SetSpeedX(-GetSpeedZ() * 0.7); + } + + SetSpeedZ(0); + SetPosZ(floor(GetPosZ()) + 0.5); + } + break; + } + case E_META_RAIL_CURVED_ZM_XP: + { + if (GetPosZ() < floor(GetPosZ()) + 0.5) + { + if (GetSpeedX() < 0) + { + SetSpeedZ(GetSpeedX() * 0.7); + } + + SetSpeedX(0); + SetPosX(floor(GetPosX()) + 0.5); + } + else + { + if (GetSpeedZ() > 0) + { + SetSpeedX(GetSpeedZ() * 0.7); + } + + SetSpeedZ(0); + SetPosZ(floor(GetPosZ()) + 0.5); + } + break; + } + case E_META_RAIL_CURVED_ZP_XM: + { + if (GetPosZ() < floor(GetPosZ()) + 0.5) + { + if (GetSpeedZ() < 0) + { + SetSpeedX(GetSpeedZ() * 0.7); + } + + SetSpeedZ(0); + SetPosZ(floor(GetPosZ()) + 0.5); + } + else + { + if (GetSpeedX() > 0) + { + SetSpeedZ(GetSpeedX() * 0.7); + } + + SetSpeedX(0); + SetPosX(floor(GetPosX()) + 0.5); + } + break; + } + case E_META_RAIL_CURVED_ZP_XP: + { + if (GetPosZ() < floor(GetPosZ()) + 0.5) + { + if (GetSpeedZ() < 0) + { + SetSpeedX(-GetSpeedZ() * 0.7); + } + + SetSpeedZ(0); + SetPosZ(floor(GetPosZ()) + 0.5); + } + else + { + if (GetSpeedX() < 0) + { + SetSpeedZ(-GetSpeedX() * 0.7); + } + + SetSpeedX(0); + SetPosX(floor(GetPosX()) + 0.5); + } + break; + } default: break; } } @@ -512,7 +623,7 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta) } } } - else + else if (GetSpeedZ() < 0) { BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) - 1); if (!IsBlockRail(Block) && g_BlockIsSolid[Block]) @@ -548,7 +659,7 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta) } } } - else + else if (GetSpeedX() < 0) { BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ())); if (!IsBlockRail(Block) && g_BlockIsSolid[Block]) @@ -596,10 +707,68 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta) +bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta) +{ + switch (a_RailMeta) + { + case E_META_RAIL_ZM_ZP: + { + cMinecartCollisionCallback MinecartCollisionCallback(GetPosition(), GetHeight(), GetWidth(), GetUniqueID(), ((m_Attachee == NULL) ? -1 : m_Attachee->GetUniqueID())); + m_World->ForEachEntity(MinecartCollisionCallback); + + if (MinecartCollisionCallback.FoundIntersection()) + { + if (MinecartCollisionCallback.GetCollidedEntityPosition().z >= GetPosZ()) + { + if (((-GetSpeedZ()) * 0.4) < 0.01) + { + AddSpeedZ(-4); + } + else + { + SetSpeedZ((-GetSpeedZ()) * 0.4); + } + } + else + { + if ((GetSpeedZ() * 0.4) < 0.01) + { + AddSpeedZ(4); + } + else + { + SetSpeedZ(GetSpeedZ() * 0.4); + } + } + return true; + } + break; + } + case E_META_RAIL_XM_XP: + { + + break; + } + case E_META_RAIL_CURVED_ZM_XM: + case E_META_RAIL_CURVED_ZM_XP: + case E_META_RAIL_CURVED_ZP_XM: + case E_META_RAIL_CURVED_ZP_XP: + { + + break; + } + default: break; + } + return false; +} + + + + void cMinecart::DoTakeDamage(TakeDamageInfo & TDI) { - if (TDI.Attacker->IsPlayer() && ((cPlayer *)TDI.Attacker)->IsGameModeCreative()) + if ((TDI.Attacker != NULL) && TDI.Attacker->IsPlayer() && ((cPlayer *)TDI.Attacker)->IsGameModeCreative()) { Destroy(); TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h index 1ebddfdda..1c3ea3220 100644 --- a/src/Entities/Minecart.h +++ b/src/Entities/Minecart.h @@ -79,10 +79,13 @@ protected: */ void HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt); - /** Snaps a minecart to a rail's axis, resetting its speed */ + /** Snaps a mincecart to a rail's axis, resetting its speed + For curved rails, it changes the cart's direction as well as snapping it to axis */ void SnapToRail(NIBBLETYPE a_RailMeta); - /** Tests is a solid block is in front of a cart, and stops the cart (and returns true) if so; returns false if no obstruction*/ + /** Tests if a solid block is in front of a cart, and stops the cart (and returns true) if so; returns false if no obstruction */ bool TestBlockCollision(NIBBLETYPE a_RailMeta); + /** Tests if this mincecart's bounding box is intersecting another entity's bounding box (collision) and pushes mincecart away */ + bool TestEntityCollision(NIBBLETYPE a_RailMeta); } ; -- cgit v1.2.3 From 8467f5dfaea596a0b7e294cf1b7dce224c41d7b9 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 19 Jan 2014 14:52:45 +0000 Subject: Added more rail functionality --- src/Blocks/BlockRail.h | 8 ++++---- src/Defines.h | 18 ++++++++++++++++++ src/Entities/Minecart.h | 14 -------------- 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index 55cadfa48..f13e987b7 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -204,7 +204,7 @@ public: bool IsUnstable(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) { - if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL) + if (!IsBlockRail(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ))) { return false; } @@ -339,11 +339,11 @@ public: { AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); NIBBLETYPE Meta; - if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL) + if (!IsBlockRail(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ))) { - if ((a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ) != E_BLOCK_RAIL) || (a_Pure != E_PURE_UPDOWN)) + if (!IsBlockRail(a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ)) || (a_Pure != E_PURE_UPDOWN)) { - if ((a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) != E_BLOCK_RAIL) || (a_Pure == E_PURE_NONE)) + if (!IsBlockRail(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)) || (a_Pure == E_PURE_NONE)) { return true; } diff --git a/src/Defines.h b/src/Defines.h index 7a86f499e..298180fb1 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -282,6 +282,24 @@ inline bool IsBlockLiquid(BLOCKTYPE a_BlockType) +inline bool IsBlockRail(BLOCKTYPE a_BlockType) +{ + switch (a_BlockType) + { + case E_BLOCK_RAIL: + case E_BLOCK_ACTIVATOR_RAIL: + case E_BLOCK_DETECTOR_RAIL: + case E_BLOCK_POWERED_RAIL: + { + return true; + } + default: return false; + } +} + + + + inline bool IsBlockTypeOfDirt(BLOCKTYPE a_BlockType) { diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h index a4ecb33ad..87f785538 100644 --- a/src/Entities/Minecart.h +++ b/src/Entities/Minecart.h @@ -15,20 +15,6 @@ -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 { -- cgit v1.2.3 From fc622ce1940c392dd5a049b8bd1c3017927894dd Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 19 Jan 2014 18:24:56 +0000 Subject: Fixed weird meta with curved rails --- src/Blocks/BlockRail.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index f13e987b7..da3783d08 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -186,22 +186,32 @@ public: } if (RailsCnt > 1) { - if (Neighbors[3] && Neighbors[0]) return E_META_RAIL_CURVED_ZP_XP; - else if (Neighbors[3] && Neighbors[1]) return E_META_RAIL_CURVED_ZP_XM; - else if (Neighbors[2] && Neighbors[0]) return E_META_RAIL_CURVED_ZM_XP; - else if (Neighbors[2] && Neighbors[1]) return E_META_RAIL_CURVED_ZM_XM; + if (Neighbors[3] && Neighbors[0] && CanThisRailCurve()) return E_META_RAIL_CURVED_ZP_XP; + else if (Neighbors[3] && Neighbors[1] && CanThisRailCurve()) return E_META_RAIL_CURVED_ZP_XM; + else if (Neighbors[2] && Neighbors[0] && CanThisRailCurve()) return E_META_RAIL_CURVED_ZM_XP; + else if (Neighbors[2] && Neighbors[1] && CanThisRailCurve()) return E_META_RAIL_CURVED_ZM_XM; else if (Neighbors[7] && Neighbors[2]) return E_META_RAIL_ASCEND_ZP; else if (Neighbors[3] && Neighbors[6]) return E_META_RAIL_ASCEND_ZM; else if (Neighbors[5] && Neighbors[0]) return E_META_RAIL_ASCEND_XM; else if (Neighbors[4] && Neighbors[1]) return E_META_RAIL_ASCEND_XP; else if (Neighbors[0] && Neighbors[1]) return E_META_RAIL_XM_XP; else if (Neighbors[2] && Neighbors[3]) return E_META_RAIL_ZM_ZP; - ASSERT(!"Weird neighbor count"); + + if (CanThisRailCurve()) + { + ASSERT(!"Weird neighbor count"); + } } return Meta; } + inline bool CanThisRailCurve(void) + { + return m_BlockType == E_BLOCK_RAIL; + } + + bool IsUnstable(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) { if (!IsBlockRail(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ))) -- cgit v1.2.3 From 9a580146e43cc5cf6c84455b75976020467da32f Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 19 Jan 2014 18:27:06 +0000 Subject: Minecart improvements and fixes * Fixed curved rails * Fixed detector rails in certain situations * Fixed powered rails and others passing bad meta to SnapToRail() --- src/Entities/Minecart.cpp | 76 +++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index c8f43a3e6..643eefb39 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -160,10 +160,17 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) if (IsBlockRail(InsideType)) AddPosY(1); // Push cart upwards } + bool WasDetectorRail = false; if (IsBlockRail(InsideType)) { - bool WasDetectorRail = false; - SnapToRail(InsideMeta); + if (InsideType == E_BLOCK_RAIL) + { + SnapToRail(InsideMeta); + } + else + { + SnapToRail(InsideMeta & 0x07); + } switch (InsideType) { @@ -180,12 +187,6 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) } AddPosition(GetSpeed() * (a_Dt / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp - - if (m_bIsOnDetectorRail && !WasDetectorRail) - { - m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07); - m_bIsOnDetectorRail = false; - } } else { @@ -193,6 +194,17 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) SetPosY(floor(GetPosY()) + 0.35); // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail super::HandlePhysics(a_Dt, *Chunk); } + + if (m_bIsOnDetectorRail && !Vector3i((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())).Equals(m_DetectorRailPosition)) + { + m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07); + m_bIsOnDetectorRail = false; + } + else if (WasDetectorRail) + { + m_bIsOnDetectorRail = true; + m_DetectorRailPosition = Vector3i((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())); + } // Broadcast positioning changes to client BroadcastMovementUpdate(); @@ -425,11 +437,11 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) { if (GetSpeedZ() > 0) { - AddSpeedZ(AccelDecelNegSpeed); + AddSpeedZ(AccelDecelSpeed); } else { - AddSpeedZ(AccelDecelSpeed); + AddSpeedZ(AccelDecelNegSpeed); } } break; @@ -465,9 +477,6 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) void cMinecart::HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) { - m_bIsOnDetectorRail = true; - m_DetectorRailPosition = Vector3i((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())); - m_World->SetBlockMeta(m_DetectorRailPosition, a_RailMeta | 0x08); HandleRailPhysics(a_RailMeta & 0x07, a_Dt); @@ -497,9 +506,20 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetPosX(floor(GetPosX()) + 0.5); break; } + // Curved rail physics: once minecart has reached more than half of the block in the direction that it is travelling in, jerk it in the direction of curvature case E_META_RAIL_CURVED_ZM_XM: { - if (GetPosZ() < floor(GetPosZ()) + 0.5) + if (GetPosZ() > floor(GetPosZ()) + 0.5) + { + if (GetSpeedZ() > 0) + { + SetSpeedX(-GetSpeedZ() * 0.7); + } + + SetSpeedZ(0); + SetPosZ(floor(GetPosZ()) + 0.5); + } + else if (GetPosX() > floor(GetPosX()) + 0.5) { if (GetSpeedX() > 0) { @@ -509,21 +529,21 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedX(0); SetPosX(floor(GetPosX()) + 0.5); } - else + break; + } + case E_META_RAIL_CURVED_ZM_XP: + { + if (GetPosZ() > floor(GetPosZ()) + 0.5) { if (GetSpeedZ() > 0) { - SetSpeedX(-GetSpeedZ() * 0.7); + SetSpeedX(GetSpeedZ() * 0.7); } SetSpeedZ(0); SetPosZ(floor(GetPosZ()) + 0.5); } - break; - } - case E_META_RAIL_CURVED_ZM_XP: - { - if (GetPosZ() < floor(GetPosZ()) + 0.5) + else if (GetPosX() < floor(GetPosX()) + 0.5) { if (GetSpeedX() < 0) { @@ -533,16 +553,6 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedX(0); SetPosX(floor(GetPosX()) + 0.5); } - else - { - if (GetSpeedZ() > 0) - { - SetSpeedX(GetSpeedZ() * 0.7); - } - - SetSpeedZ(0); - SetPosZ(floor(GetPosZ()) + 0.5); - } break; } case E_META_RAIL_CURVED_ZP_XM: @@ -557,7 +567,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedZ(0); SetPosZ(floor(GetPosZ()) + 0.5); } - else + else if (GetPosX() > floor(GetPosX()) + 0.5) { if (GetSpeedX() > 0) { @@ -581,7 +591,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedZ(0); SetPosZ(floor(GetPosZ()) + 0.5); } - else + else if (GetPosX() < floor(GetPosX()) + 0.5) { if (GetSpeedX() < 0) { -- cgit v1.2.3 From 3700ad8546dfa7649bb172610dfef4b365eb2a7b Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 19 Jan 2014 18:42:05 +0000 Subject: Added one more direction into collision checks * Added direction XM_XP * Improved performance, thanks STR and xoft --- src/Entities/Minecart.cpp | 77 +++++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 643eefb39..df1e48a60 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -720,56 +720,81 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta) bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta) { + cMinecartCollisionCallback MinecartCollisionCallback(GetPosition(), GetHeight(), GetWidth(), GetUniqueID(), ((m_Attachee == NULL) ? -1 : m_Attachee->GetUniqueID())); + int ChunkX, ChunkZ; + cChunkDef::BlockToChunk((int)floor(GetPosX()), (int)floor(GetPosZ()), ChunkX, ChunkZ); + m_World->ForEachEntityInChunk(ChunkX, ChunkZ, MinecartCollisionCallback); + + if (!MinecartCollisionCallback.FoundIntersection()) + { + return false; + } + switch (a_RailMeta) { case E_META_RAIL_ZM_ZP: { - cMinecartCollisionCallback MinecartCollisionCallback(GetPosition(), GetHeight(), GetWidth(), GetUniqueID(), ((m_Attachee == NULL) ? -1 : m_Attachee->GetUniqueID())); - m_World->ForEachEntity(MinecartCollisionCallback); - - if (MinecartCollisionCallback.FoundIntersection()) + if (MinecartCollisionCallback.GetCollidedEntityPosition().z >= GetPosZ()) { - if (MinecartCollisionCallback.GetCollidedEntityPosition().z >= GetPosZ()) + if ((-GetSpeedZ() * 0.4) < 0.01) { - if (((-GetSpeedZ()) * 0.4) < 0.01) - { - AddSpeedZ(-4); - } - else - { - SetSpeedZ((-GetSpeedZ()) * 0.4); - } + AddSpeedZ(-4); } else { - if ((GetSpeedZ() * 0.4) < 0.01) - { - AddSpeedZ(4); - } - else - { - SetSpeedZ(GetSpeedZ() * 0.4); - } + SetSpeedZ(-GetSpeedZ() * 0.4); } - return true; } - break; + else + { + if ((GetSpeedZ() * 0.4) < 0.01) + { + AddSpeedZ(4); + } + else + { + SetSpeedZ(GetSpeedZ() * 0.4); + } + } + return true; } case E_META_RAIL_XM_XP: { - - break; + if (MinecartCollisionCallback.GetCollidedEntityPosition().x >= GetPosX()) + { + if ((-GetSpeedX() * 0.4) < 0.01) + { + AddSpeedX(-4); + } + else + { + SetSpeedX(-GetSpeedX() * 0.4); + } + } + else + { + if ((GetSpeedX() * 0.4) < 0.01) + { + AddSpeedX(4); + } + else + { + SetSpeedX(GetSpeedX() * 0.4); + } + } + return true; } case E_META_RAIL_CURVED_ZM_XM: case E_META_RAIL_CURVED_ZM_XP: case E_META_RAIL_CURVED_ZP_XM: case E_META_RAIL_CURVED_ZP_XP: { - + // TODO - simply can't be bothered right now break; } default: break; } + return false; } -- cgit v1.2.3 From 83cbe8c13996747a49e940f77282ef68de87eba0 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 19 Jan 2014 19:31:17 +0000 Subject: Begin implementing ascending rails --- src/Entities/Minecart.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++-- src/Entities/Minecart.h | 3 +++ 2 files changed, 45 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index df1e48a60..6477fb1ca 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -360,6 +360,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) { SetYaw(315); // Set correct rotation server side SetPosY(floor(GetPosY()) + 0.55); // Levitate dat cart + SetSpeedY(0); TestBlockCollision(a_RailMeta); TestEntityCollision(a_RailMeta); @@ -372,6 +373,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) { SetYaw(225); SetPosY(floor(GetPosY()) + 0.55); + SetSpeedY(0); TestBlockCollision(a_RailMeta); TestEntityCollision(a_RailMeta); @@ -382,6 +384,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) { SetYaw(135); SetPosY(floor(GetPosY()) + 0.55); + SetSpeedY(0); TestBlockCollision(a_RailMeta); TestEntityCollision(a_RailMeta); @@ -392,6 +395,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) { SetYaw(45); SetPosY(floor(GetPosY()) + 0.55); + SetSpeedY(0); TestBlockCollision(a_RailMeta); TestEntityCollision(a_RailMeta); @@ -431,7 +435,8 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) SetSpeedY(0); SetSpeedX(0); - if (TestBlockCollision(a_RailMeta)) return; + bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); + if (EntCol || BlckCol) return; if (GetSpeedZ() != 0) { @@ -453,7 +458,8 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) SetSpeedY(0); SetSpeedZ(0); - if (TestBlockCollision(a_RailMeta)) return; + bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); + if (EntCol || BlckCol) return; if (GetSpeedX() != 0) { @@ -468,6 +474,27 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) } break; } + case E_META_RAIL_ASCEND_XM: + { + SetYaw(180); + SetSpeedZ(0); + + if (GetSpeedX() >= 0) + { + if (GetSpeedX() <= MAX_SPEED) + { + AddSpeedX(1); + SetSpeedY(-GetSpeedX()); + } + } + else + { + AddSpeedX(-1); + SetSpeedY(-GetSpeedX()); + } + break; + } + default: ASSERT(!"Unhandled powered rail metadata!"); break; } } @@ -479,6 +506,15 @@ void cMinecart::HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) { m_World->SetBlockMeta(m_DetectorRailPosition, a_RailMeta | 0x08); + // No special handling + HandleRailPhysics(a_RailMeta & 0x07, a_Dt); +} + + + + +void cMinecart::HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) +{ HandleRailPhysics(a_RailMeta & 0x07, a_Dt); } @@ -529,6 +565,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedX(0); SetPosX(floor(GetPosX()) + 0.5); } + SetSpeedY(0); break; } case E_META_RAIL_CURVED_ZM_XP: @@ -553,6 +590,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedX(0); SetPosX(floor(GetPosX()) + 0.5); } + SetSpeedY(0); break; } case E_META_RAIL_CURVED_ZP_XM: @@ -577,6 +615,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedX(0); SetPosX(floor(GetPosX()) + 0.5); } + SetSpeedY(0); break; } case E_META_RAIL_CURVED_ZP_XP: @@ -601,6 +640,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedX(0); SetPosX(floor(GetPosX()) + 0.5); } + SetSpeedY(0); break; } default: break; diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h index 87f785538..073e78953 100644 --- a/src/Entities/Minecart.h +++ b/src/Entities/Minecart.h @@ -65,6 +65,9 @@ protected: */ void HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt); + /** Handles activator rails - placeholder for future implementation */ + void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt); + /** Snaps a mincecart to a rail's axis, resetting its speed For curved rails, it changes the cart's direction as well as snapping it to axis */ void SnapToRail(NIBBLETYPE a_RailMeta); -- cgit v1.2.3 From 3b96fc1e547b4ed37a14c3b7fb264a1dbf142862 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 22 Jan 2014 19:29:18 +0100 Subject: Authenticator: Reduced logging levels. --- src/Authenticator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Authenticator.cpp b/src/Authenticator.cpp index 4cbe3beed..bd6db1c11 100644 --- a/src/Authenticator.cpp +++ b/src/Authenticator.cpp @@ -43,7 +43,6 @@ cAuthenticator::~cAuthenticator() -/// Read custom values from INI void cAuthenticator::ReadINI(cIniFile & IniFile) { m_Server = IniFile.GetValueSet("Authentication", "Server", DEFAULT_AUTH_SERVER); @@ -55,7 +54,6 @@ void cAuthenticator::ReadINI(cIniFile & IniFile) -/// Queues a request for authenticating a user. If the auth fails, the user is kicked void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash) { if (!m_ShouldAuthenticate) @@ -141,7 +139,9 @@ bool cAuthenticator::AuthFromAddress(const AString & a_Server, const AString & a cBlockingTCPLink Link; if (!Link.Connect(a_Server.c_str(), 80)) { - LOGERROR("cAuthenticator: cannot connect to auth server \"%s\", kicking user \"%s\"", a_Server.c_str(), a_Server.c_str()); + LOGWARNING("%s: cannot connect to auth server \"%s\", kicking user \"%s\"", + __FUNCTION__, a_Server.c_str(), a_UserName.c_str() + ); return false; } @@ -170,7 +170,7 @@ bool cAuthenticator::AuthFromAddress(const AString & a_Server, const AString & a if (code == 302) { // redirect blabla - LOGINFO("Need to redirect!"); + LOGD("%s: Need to redirect, current level %d!", __FUNCTION__, a_Level); if (a_Level > MAX_REDIRECTS) { LOGERROR("cAuthenticator: received too many levels of redirection from auth server \"%s\" for user \"%s\", bailing out and kicking the user", a_Server.c_str(), a_UserName.c_str()); -- cgit v1.2.3 From eb9bebf7558e56aab10307afc59824c728b6206f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 22 Jan 2014 22:19:33 +0100 Subject: Replacing CryptoPP with PolarSSL. This is only the CMake modification to build with PolarSSL, the actual MCS code doesn't compile at all yet. --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 275099540..ba642f7e6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -120,4 +120,4 @@ endif () if (WIN32) target_link_libraries(${EXECUTABLE} expat tolualib ws2_32.lib Psapi.lib) endif() -target_link_libraries(${EXECUTABLE} md5 luaexpat iniFile jsoncpp cryptopp zlib lua sqlite) +target_link_libraries(${EXECUTABLE} md5 luaexpat iniFile jsoncpp polarssl zlib lua sqlite) -- cgit v1.2.3 From 41b05416c75b9cbe31406f04b58b5da9892872f8 Mon Sep 17 00:00:00 2001 From: Mike Hunsinger Date: Thu, 23 Jan 2014 00:27:39 -0700 Subject: Split TossItem into three Toss functions (Held, Equipped and Pickup) --- src/ClientHandle.cpp | 5 ++- src/Entities/Player.cpp | 107 ++++++++++++++++++++++++++---------------------- src/Entities/Player.h | 9 +++- src/UI/Window.cpp | 37 ++++++++++++++--- 4 files changed, 101 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 74d192129..ab3c85ba9 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -658,7 +658,8 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } - m_Player->TossItem(false); + + m_Player->TossEquippedItem(); return; } @@ -713,7 +714,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } - m_Player->TossItem(false, 64); // Toss entire slot - if there aren't enough items, the maximum will be ejected + m_Player->TossEquippedItem(64); // Toss entire slot - if there aren't enough items, the maximum will be ejected return; } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index c1f2456eb..ca39d4d9d 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1342,59 +1342,68 @@ AString cPlayer::GetColor(void) const -void cPlayer::TossItem( - bool a_bDraggingItem, - char a_Amount /* = 1 */, - short a_CreateType /* = 0 */, - short a_CreateHealth /* = 0 */ -) +void cPlayer::TossEquippedItem(char a_Amount) { cItems Drops; - if (a_CreateType != 0) - { - // Just create item without touching the inventory (used in creative mode) - Drops.push_back(cItem(a_CreateType, a_Amount, a_CreateHealth)); - } - else - { - // Drop an item from the inventory: - if (a_bDraggingItem) - { - cItem & Item = GetDraggingItem(); - if (!Item.IsEmpty()) - { - char OriginalItemAmount = Item.m_ItemCount; - Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount); - Drops.push_back(Item); - if (OriginalItemAmount > a_Amount) - { - Item.m_ItemCount = OriginalItemAmount - (char)a_Amount; - } - else - { - Item.Empty(); - } - } - } - else - { - // Else drop equipped item - cItem DroppedItem(GetInventory().GetEquippedItem()); - if (!DroppedItem.IsEmpty()) - { - char NewAmount = a_Amount; - if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount) - { - NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there - } + cItem DroppedItem(GetInventory().GetEquippedItem()); + if (!DroppedItem.IsEmpty()) + { + char NewAmount = a_Amount; + if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount) + { + NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there + } - GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount); + GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount); + + DroppedItem.m_ItemCount = NewAmount; + Drops.push_back(DroppedItem); + } + + double vX = 0, vY = 0, vZ = 0; + EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); + vY = -vY * 2 + 1.f; + m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player +} + + + + + +void cPlayer::TossHeldItem(char a_Amount) +{ + cItems Drops; + cItem & Item = GetDraggingItem(); + if (!Item.IsEmpty()) + { + char OriginalItemAmount = Item.m_ItemCount; + Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount); + Drops.push_back(Item); + if (OriginalItemAmount > a_Amount) + { + Item.m_ItemCount = OriginalItemAmount - a_Amount; + } + else + { + Item.Empty(); + } + } + + double vX = 0, vY = 0, vZ = 0; + EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); + vY = -vY * 2 + 1.f; + m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player +} + + + + + +void cPlayer::TossPickup(const cItem & a_Item) +{ + cItems Drops; + Drops.push_back(a_Item); - DroppedItem.m_ItemCount = NewAmount; - Drops.push_back(DroppedItem); - } - } - } double vX = 0, vY = 0, vZ = 0; EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); vY = -vY * 2 + 1.f; diff --git a/src/Entities/Player.h b/src/Entities/Player.h index bf3ca08e8..71033ab77 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -214,7 +214,14 @@ public: /// Returns the full color code to use for this player, based on their primary group or set in m_Color AString GetColor(void) const; - void TossItem(bool a_bDraggingItem, char a_Amount = 1, short a_CreateType = 0, short a_CreateHealth = 0); + // tosses the item in the selected hotbar slot + void TossEquippedItem(char a_Amount = 1); + + // tosses the item held in hand (when in UI windows) + void TossHeldItem(char a_Amount = 1); + + // tosses a pickup newly created from a_Item + void TossPickup(const cItem & a_Item); /// Heals the player by the specified amount of HPs (positive only); sends health update void Heal(int a_Health); diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp index 3ffeff7a0..3dd6d2264 100644 --- a/src/UI/Window.cpp +++ b/src/UI/Window.cpp @@ -13,7 +13,8 @@ #include "../BlockEntities/DropSpenserEntity.h" #include "../BlockEntities/EnderChestEntity.h" #include "../BlockEntities/HopperEntity.h" - +#include "../Root.h" +#include "../Bindings/PluginManager.h" @@ -169,6 +170,8 @@ void cWindow::Clicked( const cItem & a_ClickedItem ) { + cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); + if (a_WindowID != m_WindowID) { LOGWARNING("%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__, m_WindowID, a_WindowID, a_Player.GetName().c_str()); @@ -179,14 +182,36 @@ void cWindow::Clicked( { case caRightClickOutside: { + if (PlgMgr->CallHookPlayerTossingItem(a_Player)) + { + // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) + return; + } + + if (a_Player.IsGameModeCreative()) + { + a_Player.TossPickup(a_ClickedItem); + } + // Toss one of the dragged items: - a_Player.TossItem(true); + a_Player.TossHeldItem(); return; } case caLeftClickOutside: { + if (PlgMgr->CallHookPlayerTossingItem(a_Player)) + { + // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) + return; + } + + if (a_Player.IsGameModeCreative()) + { + a_Player.TossPickup(a_ClickedItem); + } + // Toss all dragged items: - a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount); + a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); return; } case caLeftClickOutsideHoldNothing: @@ -259,11 +284,13 @@ void cWindow::OpenedByPlayer(cPlayer & a_Player) bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) { + cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); + // Checks whether the player is still holding an item if (a_Player.IsDraggingItem()) { - LOGD("Player holds item! Dropping it..."); - a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount); + LOGD("Player holds item! Dropping it..."); + a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } cClientHandle * ClientHandle = a_Player.GetClientHandle(); -- cgit v1.2.3 From 00d73177463936c149b31171b8d4b00daacc608d Mon Sep 17 00:00:00 2001 From: Mike Hunsinger Date: Thu, 23 Jan 2014 00:53:00 -0700 Subject: Removed extra line --- src/UI/Window.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp index 3dd6d2264..3d23dfd07 100644 --- a/src/UI/Window.cpp +++ b/src/UI/Window.cpp @@ -284,8 +284,6 @@ void cWindow::OpenedByPlayer(cPlayer & a_Player) bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) { - cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); - // Checks whether the player is still holding an item if (a_Player.IsDraggingItem()) { -- cgit v1.2.3 From 4ef61d8bf6d815b164a32bdab6a18744cbf0abd2 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 Jan 2014 14:57:04 +0200 Subject: Command block fixes 2 --- src/BlockEntities/CommandBlockEntity.cpp | 26 +++++++++++++++++----- src/ClientHandle.cpp | 25 ++++++++------------- src/World.cpp | 27 ++++++++++++++++++++++- src/World.h | 9 ++++++++ src/WorldStorage/NBTChunkSerializer.cpp | 19 ++++++++-------- src/WorldStorage/WSSCompact.cpp | 38 +++++++++++++++++++++++++------- 6 files changed, 104 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index 7e9015d33..db8eb1436 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -151,9 +151,13 @@ void cCommandBlockEntity::SendTo(cClientHandle & a_Client) bool cCommandBlockEntity::LoadFromJson(const Json::Value & a_Value) { - m_Command = a_Value.get("Command", "").asString(); + m_PosX = a_Value.get("x", 0).asInt(); + m_PosY = a_Value.get("y", 0).asInt(); + m_PosZ = a_Value.get("z", 0).asInt(); - m_LastOutput = a_Value.get("LastOutput", "").asString(); + m_Command = a_Value.get("Command", "").asString(); + m_LastOutput = a_Value.get("LastOutput", "").asString(); + m_Result = a_Value.get("SuccessCount", 0).asInt(); return true; } @@ -164,9 +168,13 @@ bool cCommandBlockEntity::LoadFromJson(const Json::Value & a_Value) void cCommandBlockEntity::SaveToJson(Json::Value & a_Value) { - a_Value["Command"] = m_Command; + a_Value["x"] = m_PosX; + a_Value["y"] = m_PosY; + a_Value["z"] = m_PosZ; - a_Value["LastOutput"] = m_LastOutput; + a_Value["Command"] = m_Command; + a_Value["LastOutput"] = m_LastOutput; + a_Value["SuccessCount"] = m_Result; } @@ -175,6 +183,14 @@ void cCommandBlockEntity::SaveToJson(Json::Value & a_Value) void cCommandBlockEntity::Execute() { + if (m_World) + { + if (!m_World->AreCommandBlocksEnabled()) + { + return; + } + } + class CommandBlockOutCb : public cCommandOutputCallback { @@ -185,8 +201,6 @@ void cCommandBlockEntity::Execute() virtual void Out(const AString & a_Text) { - ASSERT(m_CmdBlock != NULL); - // Overwrite field m_CmdBlock->SetLastOutput(a_Text); } diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 0a2d3c1be..ed04edac0 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -610,25 +610,18 @@ void cClientHandle::HandleCommandBlockMessage(const char* a_Data, unsigned int a } } - class cUpdateCommandBlock : - public cCommandBlockCallback - { - AString m_Command; - public: - cUpdateCommandBlock(const AString & a_Command) : m_Command(a_Command) {} - - virtual bool Item(cCommandBlockEntity * a_CommandBlock) override - { - a_CommandBlock->SetCommand(m_Command); - return false; - } - } CmdBlockCB (Command); - cWorld * World = m_Player->GetWorld(); - World->DoWithCommandBlockAt(BlockX, BlockY, BlockZ, CmdBlockCB); + if (World->AreCommandBlocksEnabled()) + { + World->SetCommandBlockCommand(BlockX, BlockY, BlockZ, Command); - SendChat(Printf("%s[INFO]%s Successfully set command block command", cChatColor::Green.c_str(), cChatColor::White.c_str())); + SendChat(Printf("%s[INFO]%s Successfully set command block command", cChatColor::Green.c_str(), cChatColor::White.c_str())); + } + else + { + SendChat(Printf("%s[INFO]%s Command blocks are not enabled on this server", cChatColor::Green.c_str(), cChatColor::White.c_str())); + } } diff --git a/src/World.cpp b/src/World.cpp index 49d42f08e..453a22c2d 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -22,6 +22,8 @@ #include "Entities/Player.h" #include "Entities/TNTEntity.h" +#include "BlockEntities/CommandBlockEntity.h" + // Simulators: #include "Simulator/SimulatorManager.h" #include "Simulator/FloodyFluidSimulator.h" @@ -523,7 +525,7 @@ void cWorld::Start(void) } m_StorageSchema = IniFile.GetValueSet ("Storage", "Schema", m_StorageSchema); - m_StorageCompressionFactor = IniFile.GetValueSetI ("Storage", "CompressionFactor", m_StorageCompressionFactor); + m_StorageCompressionFactor = IniFile.GetValueSetI("Storage", "CompressionFactor", m_StorageCompressionFactor); m_MaxCactusHeight = IniFile.GetValueSetI("Plants", "MaxCactusHeight", 3); m_MaxSugarcaneHeight = IniFile.GetValueSetI("Plants", "MaxSugarcaneHeight", 3); m_IsCactusBonemealable = IniFile.GetValueSetB("Plants", "IsCactusBonemealable", false); @@ -540,6 +542,7 @@ void cWorld::Start(void) m_bEnabledPVP = IniFile.GetValueSetB("PVP", "Enabled", true); m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", false); m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true); + m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false); m_GameMode = (eGameMode)IniFile.GetValueSetI("GameMode", "GameMode", m_GameMode); @@ -2611,6 +2614,28 @@ bool cWorld::UpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString +bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command) +{ + class cUpdateCommandBlock : public cCommandBlockCallback + { + AString m_Command; + public: + cUpdateCommandBlock(const AString & a_Command) : m_Command(a_Command) {} + + virtual bool Item(cCommandBlockEntity * a_CommandBlock) override + { + a_CommandBlock->SetCommand(m_Command); + return false; + } + } CmdBlockCB (a_Command); + + return DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, CmdBlockCB); +} + + + + + void cWorld::ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay) { m_ChunkMap->ChunksStay(a_Chunks, a_Stay); diff --git a/src/World.h b/src/World.h index 2d6baa99f..61c7604df 100644 --- a/src/World.h +++ b/src/World.h @@ -296,6 +296,9 @@ public: /** Sets the sign text, asking plugins for permission first. a_Player is the player who this change belongs to, may be NULL. Returns true if sign text changed. Same as SetSignLines() */ bool UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = NULL); // Exported in ManualBindings.cpp + /** Sets the command block command. Returns true if command changed. */ + bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export + /** Marks (a_Stay == true) or unmarks (a_Stay == false) chunks as non-unloadable. To be used only by cChunkStay! */ void ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay = true); @@ -511,6 +514,10 @@ public: /// Returns the associated scoreboard instance cScoreboard & GetScoreBoard(void) { return m_Scoreboard; } + + bool AreCommandBlocksEnabled(void) const { return m_bCommandBlocksEnabled; } + + void SetCommandBlocksEnabled(bool a_Flag) { m_bCommandBlocksEnabled = a_Flag; } // tolua_end @@ -774,6 +781,8 @@ private: bool m_IsPumpkinBonemealable; bool m_IsSaplingBonemealable; bool m_IsSugarcaneBonemealable; + + bool m_bCommandBlocksEnabled; cCriticalSection m_CSFastSetBlock; sSetBlockList m_FastSetBlockQueue; diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index c84128022..e46a28caa 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -652,20 +652,21 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity) m_Writer.BeginList("TileEntities", TAG_Compound); } m_IsTagOpen = true; - + // Add tile-entity into NBT: switch (a_Entity->GetBlockType()) { - case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity); break; - case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break; - case E_BLOCK_DROPPER: AddDropperEntity ((cDropperEntity *) a_Entity); break; - case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break; - case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break; + case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity); break; + case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break; + case E_BLOCK_DROPPER: AddDropperEntity ((cDropperEntity *) a_Entity); break; + case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break; + case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break; case E_BLOCK_SIGN_POST: - case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break; - case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break; - case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break; + case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break; + case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break; + case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break; case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *) a_Entity); break; + default: { ASSERT(!"Unhandled block entity saved into Anvil"); diff --git a/src/WorldStorage/WSSCompact.cpp b/src/WorldStorage/WSSCompact.cpp index ea17a8ec1..d020b73cc 100644 --- a/src/WorldStorage/WSSCompact.cpp +++ b/src/WorldStorage/WSSCompact.cpp @@ -10,6 +10,7 @@ #include "json/json.h" #include "../StringCompression.h" #include "../BlockEntities/ChestEntity.h" +#include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/JukeboxEntity.h" @@ -71,14 +72,15 @@ void cJsonChunkSerializer::BlockEntity(cBlockEntity * a_BlockEntity) const char * SaveInto = NULL; switch (a_BlockEntity->GetBlockType()) { - case E_BLOCK_CHEST: SaveInto = "Chests"; break; - case E_BLOCK_DISPENSER: SaveInto = "Dispensers"; break; - case E_BLOCK_DROPPER: SaveInto = "Droppers"; break; - case E_BLOCK_FURNACE: SaveInto = "Furnaces"; break; - case E_BLOCK_SIGN_POST: SaveInto = "Signs"; break; - case E_BLOCK_WALLSIGN: SaveInto = "Signs"; break; - case E_BLOCK_NOTE_BLOCK: SaveInto = "Notes"; break; - case E_BLOCK_JUKEBOX: SaveInto = "Jukeboxes"; break; + case E_BLOCK_CHEST: SaveInto = "Chests"; break; + case E_BLOCK_DISPENSER: SaveInto = "Dispensers"; break; + case E_BLOCK_DROPPER: SaveInto = "Droppers"; break; + case E_BLOCK_FURNACE: SaveInto = "Furnaces"; break; + case E_BLOCK_SIGN_POST: SaveInto = "Signs"; break; + case E_BLOCK_WALLSIGN: SaveInto = "Signs"; break; + case E_BLOCK_NOTE_BLOCK: SaveInto = "Notes"; break; + case E_BLOCK_JUKEBOX: SaveInto = "Jukeboxes"; break; + case E_BLOCK_COMMAND_BLOCK: SaveInto = "CommandBlocks"; break; default: { @@ -383,6 +385,26 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En } } // for itr - AllJukeboxes[] } + + // Load command blocks + Json::Value AllCommandBlocks = a_Value.get("CommandBlocks", Json::nullValue); + if( !AllCommandBlocks.empty() ) + { + for( Json::Value::iterator itr = AllCommandBlocks.begin(); itr != AllCommandBlocks.end(); ++itr ) + { + Json::Value & CommandBlock = *itr; + cCommandBlockEntity * CommandBlockEntity = new cCommandBlockEntity(0, 0, 0, a_World); + if ( !CommandBlockEntity->LoadFromJson( CommandBlock ) ) + { + LOGERROR("ERROR READING COMMAND BLOCK FROM JSON!" ); + delete CommandBlockEntity; + } + else + { + a_BlockEntities.push_back( CommandBlockEntity ); + } + } // for itr - AllCommandBlocks[] + } } -- cgit v1.2.3 From 97ee3340e302bd4bdd93054262bb9743ca37c764 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 23 Jan 2014 14:14:33 +0100 Subject: Minor style improvements for the merged PR. --- src/BlockEntities/CommandBlockEntity.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index db8eb1436..0bc6ca359 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -183,7 +183,7 @@ void cCommandBlockEntity::SaveToJson(Json::Value & a_Value) void cCommandBlockEntity::Execute() { - if (m_World) + if (m_World != NULL) { if (!m_World->AreCommandBlocksEnabled()) { @@ -194,10 +194,10 @@ void cCommandBlockEntity::Execute() class CommandBlockOutCb : public cCommandOutputCallback { - cCommandBlockEntity* m_CmdBlock; + cCommandBlockEntity * m_CmdBlock; public: - CommandBlockOutCb(cCommandBlockEntity* a_CmdBlock) : m_CmdBlock(a_CmdBlock) {} + CommandBlockOutCb(cCommandBlockEntity * a_CmdBlock) : m_CmdBlock(a_CmdBlock) {} virtual void Out(const AString & a_Text) { @@ -208,7 +208,7 @@ void cCommandBlockEntity::Execute() LOGD("cCommandBlockEntity: Executing command %s", m_Command.c_str()); - cServer* Server = cRoot::Get()->GetServer(); + cServer * Server = cRoot::Get()->GetServer(); Server->ExecuteConsoleCommand(m_Command, CmdBlockOutCb); -- cgit v1.2.3 From 9ae31d913c40c86988f12ffc51d3e9e7ab982822 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 23 Jan 2014 14:21:56 +0100 Subject: Improved code safety for the Compact world storage. That was a huge chunk of smelly code. --- src/WorldStorage/WSSCompact.cpp | 176 ++++++++++++++++------------------------ 1 file changed, 72 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/WorldStorage/WSSCompact.cpp b/src/WorldStorage/WSSCompact.cpp index d020b73cc..4c0684dd8 100644 --- a/src/WorldStorage/WSSCompact.cpp +++ b/src/WorldStorage/WSSCompact.cpp @@ -265,146 +265,114 @@ bool cWSSCompact::EraseChunkData(const cChunkCoords & a_Chunk) void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities, cWorld * a_World) { - // Load chests + // Load chests: Json::Value AllChests = a_Value.get("Chests", Json::nullValue); if (!AllChests.empty()) { for (Json::Value::iterator itr = AllChests.begin(); itr != AllChests.end(); ++itr ) { - Json::Value & Chest = *itr; - cChestEntity * ChestEntity = new cChestEntity(0,0,0, a_World); - if (!ChestEntity->LoadFromJson( Chest ) ) + std::auto_ptr ChestEntity(new cChestEntity(0, 0, 0, a_World)); + if (!ChestEntity->LoadFromJson(*itr)) { - LOGERROR("ERROR READING CHEST FROM JSON!" ); - delete ChestEntity; + LOGWARNING("ERROR READING CHEST FROM JSON!" ); } else { - a_BlockEntities.push_back( ChestEntity ); + a_BlockEntities.push_back(ChestEntity.release()); } } // for itr - AllChests[] } - // Load dispensers + // Load dispensers: Json::Value AllDispensers = a_Value.get("Dispensers", Json::nullValue); - if( !AllDispensers.empty() ) + for (Json::Value::iterator itr = AllDispensers.begin(); itr != AllDispensers.end(); ++itr) { - for( Json::Value::iterator itr = AllDispensers.begin(); itr != AllDispensers.end(); ++itr ) + std::auto_ptr DispenserEntity(new cDispenserEntity(0, 0, 0, a_World)); + if (!DispenserEntity->LoadFromJson(*itr)) { - Json::Value & Dispenser = *itr; - cDispenserEntity * DispenserEntity = new cDispenserEntity(0,0,0, a_World); - if( !DispenserEntity->LoadFromJson( Dispenser ) ) - { - LOGERROR("ERROR READING DISPENSER FROM JSON!" ); - delete DispenserEntity; - } - else - { - a_BlockEntities.push_back( DispenserEntity ); - } - } // for itr - AllDispensers[] - } + LOGWARNING("ERROR READING DISPENSER FROM JSON!" ); + } + else + { + a_BlockEntities.push_back(DispenserEntity.release()); + } + } // for itr - AllDispensers[] - // Load furnaces + // Load furnaces: Json::Value AllFurnaces = a_Value.get("Furnaces", Json::nullValue); - if( !AllFurnaces.empty() ) + for (Json::Value::iterator itr = AllFurnaces.begin(); itr != AllFurnaces.end(); ++itr) { - for( Json::Value::iterator itr = AllFurnaces.begin(); itr != AllFurnaces.end(); ++itr ) + // TODO: The block type and meta aren't correct, there's no way to get them here + std::auto_ptr FurnaceEntity(new cFurnaceEntity(0, 0, 0, E_BLOCK_FURNACE, 0, a_World)); + if (!FurnaceEntity->LoadFromJson(*itr)) { - Json::Value & Furnace = *itr; - // TODO: The block type and meta aren't correct, there's no way to get them here - cFurnaceEntity * FurnaceEntity = new cFurnaceEntity(0, 0, 0, E_BLOCK_FURNACE, 0, a_World); - if (!FurnaceEntity->LoadFromJson(Furnace)) - { - LOGERROR("ERROR READING FURNACE FROM JSON!" ); - delete FurnaceEntity; - } - else - { - a_BlockEntities.push_back(FurnaceEntity); - } - } // for itr - AllFurnaces[] - } + LOGWARNING("ERROR READING FURNACE FROM JSON!" ); + } + else + { + a_BlockEntities.push_back(FurnaceEntity.release()); + } + } // for itr - AllFurnaces[] - // Load signs + // Load signs: Json::Value AllSigns = a_Value.get("Signs", Json::nullValue); - if( !AllSigns.empty() ) + for (Json::Value::iterator itr = AllSigns.begin(); itr != AllSigns.end(); ++itr) { - for( Json::Value::iterator itr = AllSigns.begin(); itr != AllSigns.end(); ++itr ) + std::auto_ptr SignEntity(new cSignEntity(E_BLOCK_SIGN_POST, 0, 0, 0, a_World)); + if (!SignEntity->LoadFromJson(*itr)) { - Json::Value & Sign = *itr; - cSignEntity * SignEntity = new cSignEntity( E_BLOCK_SIGN_POST, 0,0,0, a_World); - if ( !SignEntity->LoadFromJson( Sign ) ) - { - LOGERROR("ERROR READING SIGN FROM JSON!" ); - delete SignEntity; - } - else - { - a_BlockEntities.push_back( SignEntity ); - } - } // for itr - AllSigns[] - } + LOGWARNING("ERROR READING SIGN FROM JSON!"); + } + else + { + a_BlockEntities.push_back(SignEntity.release()); + } + } // for itr - AllSigns[] - // Load note blocks + // Load note blocks: Json::Value AllNotes = a_Value.get("Notes", Json::nullValue); - if( !AllNotes.empty() ) + for( Json::Value::iterator itr = AllNotes.begin(); itr != AllNotes.end(); ++itr ) { - for( Json::Value::iterator itr = AllNotes.begin(); itr != AllNotes.end(); ++itr ) + std::auto_ptr NoteEntity(new cNoteEntity(0, 0, 0, a_World)); + if (!NoteEntity->LoadFromJson(*itr)) { - Json::Value & Note = *itr; - cNoteEntity * NoteEntity = new cNoteEntity(0, 0, 0, a_World); - if ( !NoteEntity->LoadFromJson( Note ) ) - { - LOGERROR("ERROR READING NOTE BLOCK FROM JSON!" ); - delete NoteEntity; - } - else - { - a_BlockEntities.push_back( NoteEntity ); - } - } // for itr - AllNotes[] - } + LOGWARNING("ERROR READING NOTE BLOCK FROM JSON!" ); + } + else + { + a_BlockEntities.push_back(NoteEntity.release()); + } + } // for itr - AllNotes[] - // Load jukeboxes + // Load jukeboxes: Json::Value AllJukeboxes = a_Value.get("Jukeboxes", Json::nullValue); - if( !AllJukeboxes.empty() ) + for( Json::Value::iterator itr = AllJukeboxes.begin(); itr != AllJukeboxes.end(); ++itr ) { - for( Json::Value::iterator itr = AllJukeboxes.begin(); itr != AllJukeboxes.end(); ++itr ) + std::auto_ptr JukeboxEntity(new cJukeboxEntity(0, 0, 0, a_World)); + if (!JukeboxEntity->LoadFromJson(*itr)) { - Json::Value & Jukebox = *itr; - cJukeboxEntity * JukeboxEntity = new cJukeboxEntity(0, 0, 0, a_World); - if ( !JukeboxEntity->LoadFromJson( Jukebox ) ) - { - LOGERROR("ERROR READING JUKEBOX FROM JSON!" ); - delete JukeboxEntity; - } - else - { - a_BlockEntities.push_back( JukeboxEntity ); - } - } // for itr - AllJukeboxes[] - } + LOGWARNING("ERROR READING JUKEBOX FROM JSON!" ); + } + else + { + a_BlockEntities.push_back(JukeboxEntity.release()); + } + } // for itr - AllJukeboxes[] - // Load command blocks + // Load command blocks: Json::Value AllCommandBlocks = a_Value.get("CommandBlocks", Json::nullValue); - if( !AllCommandBlocks.empty() ) + for( Json::Value::iterator itr = AllCommandBlocks.begin(); itr != AllCommandBlocks.end(); ++itr ) { - for( Json::Value::iterator itr = AllCommandBlocks.begin(); itr != AllCommandBlocks.end(); ++itr ) + std::auto_ptr CommandBlockEntity(new cCommandBlockEntity(0, 0, 0, a_World)); + if (!CommandBlockEntity->LoadFromJson(*itr)) { - Json::Value & CommandBlock = *itr; - cCommandBlockEntity * CommandBlockEntity = new cCommandBlockEntity(0, 0, 0, a_World); - if ( !CommandBlockEntity->LoadFromJson( CommandBlock ) ) - { - LOGERROR("ERROR READING COMMAND BLOCK FROM JSON!" ); - delete CommandBlockEntity; - } - else - { - a_BlockEntities.push_back( CommandBlockEntity ); - } - } // for itr - AllCommandBlocks[] - } + LOGWARNING("ERROR READING COMMAND BLOCK FROM JSON!" ); + } + else + { + a_BlockEntities.push_back(CommandBlockEntity.release()); + } + } // for itr - AllCommandBlocks[] } -- cgit v1.2.3 From bafa0347a349af663a6181173a2c81a73d6b29de Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 Jan 2014 16:27:23 +0200 Subject: Fixed scoreboard serialization --- src/WorldStorage/ScoreboardSerializer.cpp | 61 +++++++++++++------------------ 1 file changed, 26 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp index dabc5e2e1..d41456d15 100644 --- a/src/WorldStorage/ScoreboardSerializer.cpp +++ b/src/WorldStorage/ScoreboardSerializer.cpp @@ -13,11 +13,6 @@ -#define SCOREBOARD_INFLATE_MAX 16 KiB - - - - cScoreboardSerializer::cScoreboardSerializer(const AString & a_WorldName, cScoreboard* a_ScoreBoard) : m_ScoreBoard(a_ScoreBoard) @@ -37,37 +32,25 @@ cScoreboardSerializer::cScoreboardSerializer(const AString & a_WorldName, cScore bool cScoreboardSerializer::Load(void) { cFile File; - - if (!File.Open(FILE_IO_PREFIX + m_Path, cFile::fmReadWrite)) + if (!File.Open(FILE_IO_PREFIX + m_Path, cFile::fmRead)) { return false; } AString Data; - File.ReadRestOfFile(Data); - File.Close(); - char Uncompressed[SCOREBOARD_INFLATE_MAX]; - z_stream strm; - strm.zalloc = (alloc_func)NULL; - strm.zfree = (free_func)NULL; - strm.opaque = NULL; - inflateInit(&strm); - strm.next_out = (Bytef *)Uncompressed; - strm.avail_out = sizeof(Uncompressed); - strm.next_in = (Bytef *)Data.data(); - strm.avail_in = Data.size(); - int res = inflate(&strm, Z_FINISH); - inflateEnd(&strm); - if (res != Z_STREAM_END) + AString Uncompressed; + int res = UncompressStringGZIP(Data.data(), Data.size(), Uncompressed); + + if (res != Z_OK) { return false; } // Parse the NBT data: - cParsedNBT NBT(Uncompressed, strm.total_out); + cParsedNBT NBT(Uncompressed.data(), Uncompressed.size()); if (!NBT.IsValid()) { // NBT Parsing failed @@ -85,11 +68,8 @@ bool cScoreboardSerializer::Save(void) { cFastNBTWriter Writer; - Writer.BeginCompound(""); - m_ScoreBoard->RegisterObjective("test","test",cObjective::E_TYPE_DUMMY)->AddScore("dot", 2); SaveScoreboardToNBT(Writer); - Writer.EndCompound(); Writer.Finish(); #ifdef _DEBUG @@ -97,12 +77,22 @@ bool cScoreboardSerializer::Save(void) ASSERT(TestParse.IsValid()); #endif // _DEBUG - gzFile gz = gzopen((FILE_IO_PREFIX + m_Path).c_str(), "wb"); - if (gz != NULL) + cFile File; + if (!File.Open(FILE_IO_PREFIX + m_Path, cFile::fmWrite)) + { + return false; + } + + AString Compressed; + int res = CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); + + if (res != Z_OK) { - gzwrite(gz, Writer.GetResult().data(), Writer.GetResult().size()); + return false; } - gzclose(gz); + + File.Write(Compressed.data(), Compressed.size()); + File.Close(); return true; } @@ -130,7 +120,7 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) a_Writer.EndCompound(); } - a_Writer.EndList(); + a_Writer.EndList(); // Objectives a_Writer.BeginList("PlayerScores", TAG_Compound); @@ -151,7 +141,7 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) } } - a_Writer.EndList(); + a_Writer.EndList(); // PlayerScores a_Writer.BeginList("Teams", TAG_Compound); @@ -182,8 +172,9 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) a_Writer.EndCompound(); } - a_Writer.EndList(); - a_Writer.EndCompound(); + a_Writer.EndList(); // Teams + + a_Writer.EndCompound(); // Data a_Writer.BeginCompound("DisplaySlots"); @@ -196,7 +187,7 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::E_DISPLAY_SLOT_NAME); a_Writer.AddString("slot_2", (Objective == NULL) ? "" : Objective->GetName()); - a_Writer.EndCompound(); + a_Writer.EndCompound(); // DisplaySlots } -- cgit v1.2.3 From 5c04e216eb16a899719511c97ffb6139b2259c01 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 Jan 2014 16:42:01 +0200 Subject: Fixed scoreboard.dat structure --- src/WorldStorage/ScoreboardSerializer.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp index d41456d15..a53971dc2 100644 --- a/src/WorldStorage/ScoreboardSerializer.cpp +++ b/src/WorldStorage/ScoreboardSerializer.cpp @@ -103,7 +103,8 @@ bool cScoreboardSerializer::Save(void) void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) { - a_Writer.BeginCompound("Data"); + a_Writer.BeginCompound("data"); + a_Writer.BeginList("Objectives", TAG_Compound); for (cScoreboard::cObjectiveMap::const_iterator it = m_ScoreBoard->m_Objectives.begin(); it != m_ScoreBoard->m_Objectives.end(); ++it) @@ -174,8 +175,6 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) a_Writer.EndList(); // Teams - a_Writer.EndCompound(); // Data - a_Writer.BeginCompound("DisplaySlots"); cObjective * Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::E_DISPLAY_SLOT_LIST); @@ -188,6 +187,8 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) a_Writer.AddString("slot_2", (Objective == NULL) ? "" : Objective->GetName()); a_Writer.EndCompound(); // DisplaySlots + + a_Writer.EndCompound(); // Data } @@ -196,7 +197,7 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) { - int Data = a_NBT.FindChildByName(0, "Data"); + int Data = a_NBT.FindChildByName(0, "data"); if (Data < 0) { return false; @@ -338,7 +339,7 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) } } - int DisplaySlots = a_NBT.FindChildByName(0, "DisplaySlots"); + int DisplaySlots = a_NBT.FindChildByName(Data, "DisplaySlots"); if (DisplaySlots < 0) { return false; -- cgit v1.2.3 From 435eae38583f77154039273085d1145c80a263bb Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 23 Jan 2014 16:14:00 +0100 Subject: Fixed crash while calling disabled plugins. --- src/Bindings/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index 92c06487c..e582fde86 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -1740,7 +1740,7 @@ bool cPluginManager::DoWithPlugin(const AString & a_PluginName, cPluginCallback { // TODO: Implement locking for plugins PluginMap::iterator itr = m_Plugins.find(a_PluginName); - if (itr == m_Plugins.end()) + if ((itr == m_Plugins.end()) || (itr->second == NULL)) { return false; } -- cgit v1.2.3 From 9774da81221fbadf45a3f856e1ae09e592d7ec33 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 23 Jan 2014 17:54:38 +0100 Subject: Fixed a bug in LeakFinder. --- src/LeakFinder.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/LeakFinder.cpp b/src/LeakFinder.cpp index 9d7f185ba..42a5afe56 100644 --- a/src/LeakFinder.cpp +++ b/src/LeakFinder.cpp @@ -862,8 +862,10 @@ static int MyAllocHook(int nAllocType, void *pvData, { // RequestID was found size_t temp = g_CurrentMemUsage; - g_CurrentMemUsage -= nSize ; - g_pCRTTable->Remove(lRequest); + if (g_pCRTTable->Remove(lRequest)) + { + g_CurrentMemUsage -= nSize; + } if (g_CurrentMemUsage > temp) { printf("********************************************\n"); @@ -896,8 +898,11 @@ static int MyAllocHook(int nAllocType, void *pvData, // Try to find the RequestID in the Hash-Table, mark it that it was freed lReallocRequest = pHead->lRequest; size_t temp = g_CurrentMemUsage; - g_CurrentMemUsage -= pHead->nDataSize; bRet = g_pCRTTable->Remove(lReallocRequest); + if (bRet) + { + g_CurrentMemUsage -= pHead->nDataSize; + } if (g_CurrentMemUsage > temp) { printf("********************************************\n"); -- cgit v1.2.3 From 741957914073eb9f4a1fa0cd5ae90cc17078a623 Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 23 Jan 2014 10:25:56 -0800 Subject: Switched cEvent to use strerror_r for error messages --- src/OSSupport/Event.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/OSSupport/Event.cpp b/src/OSSupport/Event.cpp index cbacbba17..fe1128dc9 100644 --- a/src/OSSupport/Event.cpp +++ b/src/OSSupport/Event.cpp @@ -7,7 +7,9 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Event.h" - +#if not defined(_WIN32) +#include +#endif @@ -35,14 +37,18 @@ cEvent::cEvent(void) m_Event = sem_open(EventName.c_str(), O_CREAT, 777, 0 ); if (m_Event == SEM_FAILED) { - LOGERROR("cEvent: Cannot create event, errno = %i. Aborting server.", errno); + char buffer[1024]; + strerror_r(errno,buffer,1024); + LOGERROR("cEvent: Cannot create event, err = %s. Aborting server.", buffer); abort(); } // Unlink the semaphore immediately - it will continue to function but will not pollute the namespace // We don't store the name, so can't call this in the destructor if (sem_unlink(EventName.c_str()) != 0) { - LOGWARN("ERROR: Could not unlink cEvent. (%i)", errno); + char buffer[1024]; + strerror_r(errno,buffer,1024); + LOGWARN("ERROR: Could not unlink cEvent. (%s)", buffer); } } #endif // *nix @@ -61,7 +67,9 @@ cEvent::~cEvent() { if (sem_close(m_Event) != 0) { - LOGERROR("ERROR: Could not close cEvent. (%i)", errno); + char buffer[1024]; + strerror_r(errno,buffer,1024); + LOGERROR("ERROR: Could not close cEvent. (%s)", buffer); } } else @@ -88,7 +96,9 @@ void cEvent::Wait(void) int res = sem_wait(m_Event); if (res != 0 ) { - LOGWARN("cEvent: waiting for the event failed: %i, errno = %i. Continuing, but server may be unstable.", res, errno); + char buffer[1024]; + strerror_r(errno,buffer,1024); + LOGWARN("cEvent: waiting for the event failed: %i, err = %s. Continuing, but server may be unstable.", res, buffer); } #endif } @@ -108,7 +118,9 @@ void cEvent::Set(void) int res = sem_post(m_Event); if (res != 0) { - LOGWARN("cEvent: Could not set cEvent: %i, errno = %d", res, errno); + char buffer[1024]; + strerror_r(errno,buffer,1024); + LOGWARN("cEvent: Could not set cEvent: %i, err = %s", res, buffer); } #endif } -- cgit v1.2.3 From e0956be0a7905451666cc6d6a3bbf088d3293f21 Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 23 Jan 2014 10:41:08 -0800 Subject: added dependecies for bindings regen --- src/Bindings/CMakeLists.txt | 14 -------------- src/CMakeLists.txt | 46 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt index 50b81e42a..c181f4355 100644 --- a/src/Bindings/CMakeLists.txt +++ b/src/Bindings/CMakeLists.txt @@ -4,20 +4,6 @@ project (MCServer) # NOTE: This CMake file is processed only for Unix builds; Windows(MSVC) builds handle all the subfolders in /src in a single file, /src/CMakeLists.txt -include_directories ("${PROJECT_SOURCE_DIR}/../") - -ADD_CUSTOM_COMMAND( - # add any new generated bindings here - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Bindings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Bindings.h - - # command execuded to regerate bindings - COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - - # add any new generation dependencies here - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/virtual_method_hooks.lua ${CMAKE_CURRENT_SOURCE_DIR}/AllToLua.pkg tolua -) - #add cpp files here add_library(Bindings PluginManager LuaState WebPlugin Bindings ManualBindings LuaWindow Plugin PluginLua WebPlugin) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 275099540..08b4971b0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,52 @@ set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities) if (NOT MSVC) + + #Bindings needs to reference other folders so are done here + + #lib dependecies are not included + + set(BINDING_DEPENDECIES ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} toluaGlobals.h ChunkDef.h BiomeDef.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} OSSupport/File.h Bindings/LuaFunctions.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginManager.h Bindings/Plugin.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginLua.h Bindings/WebPlugin.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/LuaWindow.h BlockID.h StringUtils.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Defines.h ChatColor.h ClientHandle.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Entity.h Entities/Floater.h ) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Pawn.h Entities/Player.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Pickup.h Entities/ProjectileEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/TNTEntity.h Entities/Effects.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Server.h World.h Inventory.h Enchantments.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Item.h ItemGrid.h BlockEntities/BlockEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/BlockEntityWithItems.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/ChestEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DropSpenserEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DispenserEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DropperEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/FurnaceEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/HopperEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/JukeboxEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/NoteEntity.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/SignEntity.h WebAdmin.h Root.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Vector3f.h Vector3d.h Vector3i.h Matrix4f.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Cuboid.h BoundingBox.h Tracer.h Group.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockArea.h Generating/ChunkDesc.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} CraftingRecipes.h UI/Window.h Mobs/Monster.h) + + ADD_CUSTOM_COMMAND( + # add any new generated bindings here + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.h + + # command execuded to regerate bindings + COMMAND tolua -L Bindings/virtual_method_hooks.lua -o Bindings/Bindings.cpp -H Bindings/Bindings.h Bindings/AllToLua.pkg + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/ + + # add any new generation dependencies here + DEPENDS ${BINDING_DEPENDECIES} + ) + foreach(folder ${FOLDERS}) add_subdirectory(${folder}) endforeach(folder) -- cgit v1.2.3 From 27d1d5d4910460f047fdc2412e78952876f40729 Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 23 Jan 2014 11:00:36 -0800 Subject: Bugfixes --- src/Bindings/CMakeLists.txt | 10 ---------- src/CMakeLists.txt | 11 +++++++++-- 2 files changed, 9 insertions(+), 12 deletions(-) delete mode 100644 src/Bindings/CMakeLists.txt (limited to 'src') diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt deleted file mode 100644 index c181f4355..000000000 --- a/src/Bindings/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ - -cmake_minimum_required (VERSION 2.6) -project (MCServer) - -# NOTE: This CMake file is processed only for Unix builds; Windows(MSVC) builds handle all the subfolders in /src in a single file, /src/CMakeLists.txt - -#add cpp files here -add_library(Bindings PluginManager LuaState WebPlugin Bindings ManualBindings LuaWindow Plugin PluginLua WebPlugin) - -target_link_libraries(Bindings lua sqlite tolualib) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 08b4971b0..309e1ce5b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,7 +18,7 @@ if (NOT MSVC) set(BINDING_DEPENDECIES ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua) set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} toluaGlobals.h ChunkDef.h BiomeDef.h) + set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ChunkDef.h BiomeDef.h) set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} OSSupport/File.h Bindings/LuaFunctions.h) set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginManager.h Bindings/Plugin.h) set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginLua.h Bindings/WebPlugin.h) @@ -45,17 +45,24 @@ if (NOT MSVC) set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockArea.h Generating/ChunkDesc.h) set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} CraftingRecipes.h UI/Window.h Mobs/Monster.h) + include_directories(Bindings) + include_directories(.) + ADD_CUSTOM_COMMAND( # add any new generated bindings here OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.h # command execuded to regerate bindings - COMMAND tolua -L Bindings/virtual_method_hooks.lua -o Bindings/Bindings.cpp -H Bindings/Bindings.h Bindings/AllToLua.pkg + COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/ # add any new generation dependencies here DEPENDS ${BINDING_DEPENDECIES} ) + #add cpp files here + add_library(Bindings Bindings/PluginManager Bindings/LuaState Bindings/WebPlugin Bindings/Bindings Bindings/ManualBindings Bindings/LuaWindow Bindings/Plugin Bindings/PluginLua Bindings/WebPlugin) + + target_link_libraries(Bindings lua sqlite tolualib) foreach(folder ${FOLDERS}) add_subdirectory(${folder}) -- cgit v1.2.3 From ce2fb844aa0fc60af5556ccd1cd9fe316d18dd19 Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 23 Jan 2014 11:03:49 -0800 Subject: Removed Bindings folder subcmake on *nix --- src/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 309e1ce5b..c61563bd2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,7 +5,7 @@ project (MCServer) include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/") include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/jsoncpp/include") -set(FOLDERS OSSupport HTTPServer Bindings Items Blocks Protocol Generating) +set(FOLDERS OSSupport HTTPServer Items Blocks Protocol Generating) set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities) @@ -97,6 +97,7 @@ else () # Add all subfolders as solution-folders: list(APPEND FOLDERS "Resources") + list(APPEND FOLDERS "Bindings") function(includefolder PATH) FILE(GLOB FOLDER_FILES "${PATH}/*.cpp" -- cgit v1.2.3 From b21b682d851ac64bae0751a6a6ea3ca77bc4ddf7 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 23 Jan 2014 21:06:05 +0200 Subject: Fixed 1.5.x scoreboard packet IDs --- src/Protocol/Protocol15x.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Protocol/Protocol15x.cpp b/src/Protocol/Protocol15x.cpp index c33aec7d5..264a596b9 100644 --- a/src/Protocol/Protocol15x.cpp +++ b/src/Protocol/Protocol15x.cpp @@ -37,9 +37,9 @@ enum { PACKET_WINDOW_OPEN = 0x64, PACKET_PARTICLE_EFFECT = 0x3F, - PACKET_SCOREBOARD_OBJECTIVE = 0x3B, - PACKET_SCORE_UPDATE = 0x3C, - PACKET_DISPLAY_OBJECTIVE = 0x3D + PACKET_SCOREBOARD_OBJECTIVE = 0xCE, + PACKET_SCORE_UPDATE = 0xCF, + PACKET_DISPLAY_OBJECTIVE = 0xD0 } ; -- cgit v1.2.3 From b95e005d911722fec4a7a728d73c4371cb490e46 Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 23 Jan 2014 11:06:42 -0800 Subject: Make clean now effects Bindings --- src/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c61563bd2..51182d3bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,8 @@ if (NOT MSVC) target_link_libraries(Bindings lua sqlite tolualib) + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "Bindings.cpp Bindings.h") + foreach(folder ${FOLDERS}) add_subdirectory(${folder}) endforeach(folder) -- cgit v1.2.3 From 5f34c78091a7c884a9c27c0f0691cd1f03174dfe Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 23 Jan 2014 23:35:23 +0100 Subject: PolarSSL is fully used for 1.3.2 protocol encryption. --- src/CMakeLists.txt | 1 + src/Crypto.cpp | 401 ++++++++++++++++++++++++++++++++++++ src/Crypto.h | 164 +++++++++++++++ src/Defines.h | 2 - src/Globals.h | 3 + src/Protocol/Protocol132.cpp | 149 +++----------- src/Protocol/Protocol132.h | 16 +- src/Protocol/Protocol14x.cpp | 2 - src/Protocol/Protocol17x.cpp | 8 +- src/Protocol/Protocol17x.h | 13 +- src/Protocol/ProtocolRecognizer.cpp | 2 +- src/Server.cpp | 12 +- src/Server.h | 14 +- 13 files changed, 630 insertions(+), 157 deletions(-) create mode 100644 src/Crypto.cpp create mode 100644 src/Crypto.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba642f7e6..ab3b2786e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ project (MCServer) include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/") include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/jsoncpp/include") +include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/polarssl/include") set(FOLDERS OSSupport HTTPServer Bindings Items Blocks Protocol Generating) set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities) diff --git a/src/Crypto.cpp b/src/Crypto.cpp new file mode 100644 index 000000000..5ad866f34 --- /dev/null +++ b/src/Crypto.cpp @@ -0,0 +1,401 @@ + +// Crypto.cpp + +// Implements classes that wrap the cryptographic code library + +#include "Globals.h" +#include "Crypto.h" + +#include "polarssl/pk.h" + + + + + +/* +// Self-test the hash formatting for known values: +// sha1(Notch) : 4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48 +// sha1(jeb_) : -7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1 +// sha1(simon) : 88e16a1019277b15d58faf0541e11910eb756f6 + +class Test +{ +public: + Test(void) + { + AString DigestNotch, DigestJeb, DigestSimon; + Byte Digest[20]; + cSHA1Checksum Checksum; + Checksum.Update((const Byte *)"Notch", 5); + Checksum.Finalize(Digest); + cSHA1Checksum::DigestToJava(Digest, DigestNotch); + Checksum.Restart(); + Checksum.Update((const Byte *)"jeb_", 4); + Checksum.Finalize(Digest); + cSHA1Checksum::DigestToJava(Digest, DigestJeb); + Checksum.Restart(); + Checksum.Update((const Byte *)"simon", 5); + Checksum.Finalize(Digest); + cSHA1Checksum::DigestToJava(Digest, DigestSimon); + printf("Notch: \"%s\"\n", DigestNotch.c_str()); + printf("jeb_: \"%s\"\n", DigestJeb.c_str()); + printf("simon: \"%s\"\n", DigestSimon.c_str()); + assert(DigestNotch == "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48"); + assert(DigestJeb == "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1"); + assert(DigestSimon == "88e16a1019277b15d58faf0541e11910eb756f6"); + } +} test; +*/ + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cRSAPrivateKey: + +cRSAPrivateKey::cRSAPrivateKey(void) +{ + rsa_init(&m_Rsa, RSA_PKCS_V15, 0); + InitRnd(); +} + + + + + +cRSAPrivateKey::cRSAPrivateKey(const cRSAPrivateKey & a_Other) +{ + rsa_init(&m_Rsa, RSA_PKCS_V15, 0); + rsa_copy(&m_Rsa, &a_Other.m_Rsa); + InitRnd(); +} + + + + + +cRSAPrivateKey::~cRSAPrivateKey() +{ + entropy_free(&m_Entropy); + rsa_free(&m_Rsa); +} + + + + + +void cRSAPrivateKey::InitRnd(void) +{ + entropy_init(&m_Entropy); + const unsigned char pers[] = "rsa_genkey"; + ctr_drbg_init(&m_Ctr_drbg, entropy_func, &m_Entropy, pers, sizeof(pers) - 1); +} + + + + + +bool cRSAPrivateKey::Generate(unsigned a_KeySizeBits) +{ + if (rsa_gen_key(&m_Rsa, ctr_drbg_random, &m_Ctr_drbg, a_KeySizeBits, 65537) != 0) + { + // Key generation failed + return false; + } + + return true; +} + + + + + +AString cRSAPrivateKey::GetPubKeyDER(void) +{ + class cPubKey + { + public: + cPubKey(rsa_context * a_Rsa) : + m_IsValid(false) + { + pk_init(&m_Key); + if (pk_init_ctx(&m_Key, pk_info_from_type(POLARSSL_PK_RSA)) != 0) + { + ASSERT(!"Cannot init PrivKey context"); + return; + } + if (rsa_copy(pk_rsa(m_Key), a_Rsa) != 0) + { + ASSERT(!"Cannot copy PrivKey to PK context"); + return; + } + m_IsValid = true; + } + + ~cPubKey() + { + if (m_IsValid) + { + pk_free(&m_Key); + } + } + + operator pk_context * (void) { return &m_Key; } + + protected: + bool m_IsValid; + pk_context m_Key; + } PkCtx(&m_Rsa); + + unsigned char buf[3000]; + int res = pk_write_pubkey_der(PkCtx, buf, sizeof(buf)); + if (res < 0) + { + return AString(); + } + return AString((const char *)(buf + sizeof(buf) - res), (size_t)res); +} + + + + + +int cRSAPrivateKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength) +{ + if (a_EncryptedLength < m_Rsa.len) + { + LOGD("%s: Invalid a_EncryptedLength: got %u, exp at least %u", + __FUNCTION__, (unsigned)a_EncryptedLength, (unsigned)(m_Rsa.len) + ); + ASSERT(!"Invalid a_DecryptedMaxLength!"); + return -1; + } + if (a_DecryptedMaxLength < m_Rsa.len) + { + LOGD("%s: Invalid a_DecryptedMaxLength: got %u, exp at least %u", + __FUNCTION__, (unsigned)a_EncryptedLength, (unsigned)(m_Rsa.len) + ); + ASSERT(!"Invalid a_DecryptedMaxLength!"); + return -1; + } + size_t DecryptedLength; + int res = rsa_pkcs1_decrypt( + &m_Rsa, ctr_drbg_random, &m_Ctr_drbg, RSA_PRIVATE, &DecryptedLength, + a_EncryptedData, a_DecryptedData, a_DecryptedMaxLength + ); + if (res != 0) + { + return -1; + } + return (int)DecryptedLength; +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cAESCFBDecryptor: + +cAESCFBDecryptor::cAESCFBDecryptor(void) : + m_IsValid(false), + m_IVOffset(0) +{ +} + + + + + +cAESCFBDecryptor::~cAESCFBDecryptor() +{ + // Clear the leftover in-memory data, so that they can't be accessed by a backdoor + memset(&m_Aes, 0, sizeof(m_Aes)); +} + + + + + +void cAESCFBDecryptor::Init(const Byte a_Key[16], const Byte a_IV[16]) +{ + ASSERT(!IsValid()); // Cannot Init twice + + memcpy(m_IV, a_IV, 16); + aes_setkey_enc(&m_Aes, a_Key, 128); + m_IsValid = true; +} + + + + + +void cAESCFBDecryptor::ProcessData(Byte * a_DecryptedOut, const Byte * a_EncryptedIn, size_t a_Length) +{ + ASSERT(IsValid()); // Must Init() first + + // PolarSSL doesn't support AES-CFB8, need to implement it manually: + for (size_t i = 0; i < a_Length; i++) + { + Byte Buffer[sizeof(m_IV)]; + aes_crypt_ecb(&m_Aes, AES_ENCRYPT, m_IV, Buffer); + for (size_t idx = 0; idx < sizeof(m_IV) - 1; idx++) + { + m_IV[idx] = m_IV[idx + 1]; + } + m_IV[sizeof(m_IV) - 1] = a_EncryptedIn[i]; + a_DecryptedOut[i] = a_EncryptedIn[i] ^ Buffer[0]; + } +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cAESCFBEncryptor: + +cAESCFBEncryptor::cAESCFBEncryptor(void) : + m_IsValid(false), + m_IVOffset(0) +{ +} + + + + + +cAESCFBEncryptor::~cAESCFBEncryptor() +{ + // Clear the leftover in-memory data, so that they can't be accessed by a backdoor + memset(&m_Aes, 0, sizeof(m_Aes)); +} + + + + + +void cAESCFBEncryptor::Init(const Byte a_Key[16], const Byte a_IV[16]) +{ + ASSERT(!IsValid()); // Cannot Init twice + ASSERT(m_IVOffset == 0); + + memcpy(m_IV, a_IV, 16); + aes_setkey_enc(&m_Aes, a_Key, 128); + m_IsValid = true; +} + + + + + +void cAESCFBEncryptor::ProcessData(Byte * a_EncryptedOut, const Byte * a_PlainIn, size_t a_Length) +{ + ASSERT(IsValid()); // Must Init() first + + // PolarSSL doesn't do AES-CFB8, so we need to implement it ourselves: + for (size_t i = 0; i < a_Length; i++) + { + Byte Buffer[sizeof(m_IV)]; + aes_crypt_ecb(&m_Aes, AES_ENCRYPT, m_IV, Buffer); + for (size_t idx = 0; idx < sizeof(m_IV) - 1; idx++) + { + m_IV[idx] = m_IV[idx + 1]; + } + a_EncryptedOut[i] = a_PlainIn[i] ^ Buffer[0]; + m_IV[sizeof(m_IV) - 1] = a_EncryptedOut[i]; + } +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cSHA1Checksum: + +cSHA1Checksum::cSHA1Checksum(void) : + m_DoesAcceptInput(true) +{ + sha1_starts(&m_Sha1); +} + + + + + +void cSHA1Checksum::Update(const Byte * a_Data, size_t a_Length) +{ + ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed + + sha1_update(&m_Sha1, a_Data, a_Length); +} + + + + + +void cSHA1Checksum::Finalize(cSHA1Checksum::Checksum & a_Output) +{ + ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed + + sha1_finish(&m_Sha1, a_Output); + m_DoesAcceptInput = false; +} + + + + + +void cSHA1Checksum::DigestToJava(const Checksum & a_Digest, AString & a_Out) +{ + Checksum Digest; + memcpy(Digest, a_Digest, sizeof(Digest)); + + bool IsNegative = (Digest[0] >= 0x80); + if (IsNegative) + { + // Two's complement: + bool carry = true; // Add one to the whole number + for (int i = 19; i >= 0; i--) + { + Digest[i] = ~Digest[i]; + if (carry) + { + carry = (Digest[i] == 0xff); + Digest[i]++; + } + } + } + a_Out.clear(); + a_Out.reserve(40); + for (int i = 0; i < 20; i++) + { + AppendPrintf(a_Out, "%02x", Digest[i]); + } + while ((a_Out.length() > 0) && (a_Out[0] == '0')) + { + a_Out.erase(0, 1); + } + if (IsNegative) + { + a_Out.insert(0, "-"); + } +} + + + + + + +void cSHA1Checksum::Restart(void) +{ + sha1_starts(&m_Sha1); + m_DoesAcceptInput = true; +} + + + + diff --git a/src/Crypto.h b/src/Crypto.h new file mode 100644 index 000000000..6b576f55b --- /dev/null +++ b/src/Crypto.h @@ -0,0 +1,164 @@ + +// Crypto.h + +// Declares classes that wrap the cryptographic code library + + + + + +#pragma once + +#include "polarssl/rsa.h" +#include "polarssl/aes.h" +#include "polarssl/entropy.h" +#include "polarssl/ctr_drbg.h" +#include "polarssl/sha1.h" + + + + + +/** Encapsulates an RSA private key used in PKI cryptography */ +class cRSAPrivateKey +{ +public: + /** Creates a new empty object, the key is not assigned */ + cRSAPrivateKey(void); + + /** Deep-copies the key from a_Other */ + cRSAPrivateKey(const cRSAPrivateKey & a_Other); + + ~cRSAPrivateKey(); + + /** Generates a new key within this object, with the specified size in bits. + Returns true on success, false on failure. */ + bool Generate(unsigned a_KeySizeBits = 1024); + + /** Returns the public key part encoded in ASN1 DER encoding */ + AString GetPubKeyDER(void); + + /** Decrypts the data using RSAES-PKCS#1 algorithm. + Both a_EncryptedData and a_DecryptedData must be at least bytes large. + Returns the number of bytes decrypted, or negative number for error. */ + int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength); + +protected: + rsa_context m_Rsa; + entropy_context m_Entropy; + ctr_drbg_context m_Ctr_drbg; + + /** Initializes the m_Entropy and m_Ctr_drbg contexts + Common part of this object's construction, called from all constructors. */ + void InitRnd(void); +} ; + + + + + +/** Decrypts data using the AES / CFB (128) algorithm */ +class cAESCFBDecryptor +{ +public: + Byte test; + + cAESCFBDecryptor(void); + ~cAESCFBDecryptor(); + + /** Initializes the decryptor with the specified Key / IV */ + void Init(const Byte a_Key[16], const Byte a_IV[16]); + + /** Decrypts a_Length bytes of the encrypted data; produces a_Length output bytes */ + void ProcessData(Byte * a_DecryptedOut, const Byte * a_EncryptedIn, size_t a_Length); + + /** Returns true if the object has been initialized with the Key / IV */ + bool IsValid(void) const { return m_IsValid; } + +protected: + aes_context m_Aes; + + /** The InitialVector, used by the CFB mode decryption */ + Byte m_IV[16]; + + /** Current offset in the m_IV, used by the CFB mode decryption */ + size_t m_IVOffset; + + /** Indicates whether the object has been initialized with the Key / IV */ + bool m_IsValid; +} ; + + + + + +/** Encrypts data using the AES / CFB (128) algorithm */ +class cAESCFBEncryptor +{ +public: + Byte test; + + cAESCFBEncryptor(void); + ~cAESCFBEncryptor(); + + /** Initializes the decryptor with the specified Key / IV */ + void Init(const Byte a_Key[16], const Byte a_IV[16]); + + /** Encrypts a_Length bytes of the plain data; produces a_Length output bytes */ + void ProcessData(Byte * a_EncryptedOut, const Byte * a_PlainIn, size_t a_Length); + + /** Returns true if the object has been initialized with the Key / IV */ + bool IsValid(void) const { return m_IsValid; } + +protected: + aes_context m_Aes; + + /** The InitialVector, used by the CFB mode encryption */ + Byte m_IV[16]; + + /** Current offset in the m_IV, used by the CFB mode encryption */ + size_t m_IVOffset; + + /** Indicates whether the object has been initialized with the Key / IV */ + bool m_IsValid; +} ; + + + + + +/** Calculates a SHA1 checksum for data stream */ +class cSHA1Checksum +{ +public: + typedef Byte Checksum[20]; // The type used for storing the checksum + + cSHA1Checksum(void); + + /** Adds the specified data to the checksum */ + void Update(const Byte * a_Data, size_t a_Length); + + /** Calculates and returns the final checksum */ + void Finalize(Checksum & a_Output); + + /** Returns true if the object is accepts more input data, false if Finalize()-d (need to Restart()) */ + bool DoesAcceptInput(void) const { return m_DoesAcceptInput; } + + /** Converts a raw 160-bit SHA1 digest into a Java Hex representation + According to http://wiki.vg/wiki/index.php?title=Protocol_Encryption&oldid=2802 + */ + static void DigestToJava(const Checksum & a_Digest, AString & a_JavaOut); + + /** Clears the current context and start a new checksum calculation */ + void Restart(void); + +protected: + /** True if the object is accepts more input data, false if Finalize()-d (need to Restart()) */ + bool m_DoesAcceptInput; + + sha1_context m_Sha1; +} ; + + + + diff --git a/src/Defines.h b/src/Defines.h index 7a86f499e..0dcc3214a 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -5,8 +5,6 @@ -typedef unsigned char Byte; - /// List of slot numbers, used for inventory-painting typedef std::vector cSlotNums; diff --git a/src/Globals.h b/src/Globals.h index d2080b8eb..7e53da80e 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -91,6 +91,9 @@ typedef unsigned long long UInt64; typedef unsigned int UInt32; typedef unsigned short UInt16; +typedef unsigned char Byte; + + diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp index b4ca37d37..f5fd95c7e 100644 --- a/src/Protocol/Protocol132.cpp +++ b/src/Protocol/Protocol132.cpp @@ -28,13 +28,14 @@ #pragma warning(disable:4702) #endif -#include "cryptopp/randpool.h" - #ifdef _MSC_VER #pragma warning(pop) #endif + + + #define HANDLE_PACKET_READ(Proc, Type, Var) \ Type Var; \ { \ @@ -49,17 +50,6 @@ -typedef unsigned char Byte; - - - - - -using namespace CryptoPP; - - - - const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... @@ -93,81 +83,6 @@ enum -// Converts a raw 160-bit SHA1 digest into a Java Hex representation -// According to http://wiki.vg/wiki/index.php?title=Protocol_Encryption&oldid=2802 -static void DigestToJava(byte a_Digest[20], AString & a_Out) -{ - bool IsNegative = (a_Digest[0] >= 0x80); - if (IsNegative) - { - // Two's complement: - bool carry = true; // Add one to the whole number - for (int i = 19; i >= 0; i--) - { - a_Digest[i] = ~a_Digest[i]; - if (carry) - { - carry = (a_Digest[i] == 0xff); - a_Digest[i]++; - } - } - } - a_Out.clear(); - a_Out.reserve(40); - for (int i = 0; i < 20; i++) - { - AppendPrintf(a_Out, "%02x", a_Digest[i]); - } - while ((a_Out.length() > 0) && (a_Out[0] == '0')) - { - a_Out.erase(0, 1); - } - if (IsNegative) - { - a_Out.insert(0, "-"); - } -} - - - - - -/* -// Self-test the hash formatting for known values: -// sha1(Notch) : 4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48 -// sha1(jeb_) : -7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1 -// sha1(simon) : 88e16a1019277b15d58faf0541e11910eb756f6 - -class Test -{ -public: - Test(void) - { - AString DigestNotch, DigestJeb, DigestSimon; - byte Digest[20]; - CryptoPP::SHA1 Checksum; - Checksum.Update((const byte *)"Notch", 5); - Checksum.Final(Digest); - DigestToJava(Digest, DigestNotch); - Checksum.Restart(); - Checksum.Update((const byte *)"jeb_", 4); - Checksum.Final(Digest); - DigestToJava(Digest, DigestJeb); - Checksum.Restart(); - Checksum.Update((const byte *)"simon", 5); - Checksum.Final(Digest); - DigestToJava(Digest, DigestSimon); - printf("Notch: \"%s\"", DigestNotch.c_str()); - printf("jeb_: \"%s\"", DigestJeb.c_str()); - printf("simon: \"%s\"", DigestSimon.c_str()); - } -} test; -*/ - - - - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cProtocol132: @@ -197,11 +112,11 @@ void cProtocol132::DataReceived(const char * a_Data, int a_Size) { if (m_IsEncrypted) { - byte Decrypted[512]; + Byte Decrypted[512]; while (a_Size > 0) { int NumBytes = (a_Size > (int)sizeof(Decrypted)) ? (int)sizeof(Decrypted) : a_Size; - m_Decryptor.ProcessData(Decrypted, (byte *)a_Data, NumBytes); + m_Decryptor.ProcessData(Decrypted, (Byte *)a_Data, NumBytes); super::DataReceived((const char *)Decrypted, NumBytes); a_Size -= NumBytes; a_Data += NumBytes; @@ -582,9 +497,7 @@ int cProtocol132::ParseHandshake(void) return PARSE_OK; // Player is not allowed into the server } - // Send a 0xFD Encryption Key Request http://wiki.vg/Protocol#0xFD - CryptoPP::StringSink sink(m_ServerPublicKey); // GCC won't allow inline instantiation in the following line, damned temporary refs - cRoot::Get()->GetServer()->GetPublicKey().Save(sink); + // Send a 0xfd Encryption Key Request http://wiki.vg/Protocol#0xFD SendEncryptionKeyRequest(); return PARSE_OK; @@ -596,7 +509,7 @@ int cProtocol132::ParseHandshake(void) int cProtocol132::ParseClientStatuses(void) { - HANDLE_PACKET_READ(ReadByte, byte, Status); + HANDLE_PACKET_READ(ReadByte, Byte, Status); if ((Status & 1) == 0) { m_Client->HandleLogin(39, m_Username); @@ -714,11 +627,11 @@ void cProtocol132::Flush(void) int a_Size = m_DataToSend.size(); if (m_IsEncrypted) { - byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks) + Byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks) while (a_Size > 0) { int NumBytes = (a_Size > (int)sizeof(Encrypted)) ? (int)sizeof(Encrypted) : a_Size; - m_Encryptor.ProcessData(Encrypted, (byte *)a_Data, NumBytes); + m_Encryptor.ProcessData(Encrypted, (Byte *)a_Data, NumBytes); super::SendData((const char *)Encrypted, NumBytes); a_Size -= NumBytes; a_Data += NumBytes; @@ -880,8 +793,8 @@ void cProtocol132::SendEncryptionKeyRequest(void) cCSLock Lock(m_CSPacket); WriteByte(0xfd); WriteString(cRoot::Get()->GetServer()->GetServerID()); - WriteShort((short)m_ServerPublicKey.size()); - SendData(m_ServerPublicKey.data(), m_ServerPublicKey.size()); + WriteShort((short)(cRoot::Get()->GetServer()->GetPublicKeyDER().size())); + SendData(cRoot::Get()->GetServer()->GetPublicKeyDER().data(), cRoot::Get()->GetServer()->GetPublicKeyDER().size()); WriteShort(4); WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :) Flush(); @@ -894,13 +807,11 @@ void cProtocol132::SendEncryptionKeyRequest(void) void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce) { // Decrypt EncNonce using privkey - RSAES::Decryptor rsaDecryptor(cRoot::Get()->GetServer()->GetPrivateKey()); - time_t CurTime = time(NULL); - CryptoPP::RandomPool rng; - rng.Put((const byte *)&CurTime, sizeof(CurTime)); + cRSAPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey(); + Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)]; - DecodingResult res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncNonce.data(), a_EncNonce.size(), (byte *)DecryptedNonce); - if (!res.isValidCoding || (res.messageLength != 4)) + int res = rsaDecryptor.Decrypt((const Byte *)a_EncNonce.data(), a_EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce)); + if (res != 4) { LOGD("Bad nonce length"); m_Client->Kick("Hacked client"); @@ -914,9 +825,9 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A } // Decrypt the symmetric encryption key using privkey: - byte DecryptedKey[MAX_ENC_LEN]; - res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncKey.data(), a_EncKey.size(), DecryptedKey); - if (!res.isValidCoding || (res.messageLength != 16)) + Byte DecryptedKey[MAX_ENC_LEN]; + res = rsaDecryptor.Decrypt((const Byte *)a_EncKey.data(), a_EncKey.size(), DecryptedKey, sizeof(DecryptedKey)); + if (res != 16) { LOGD("Bad key length"); m_Client->Kick("Hacked client"); @@ -932,6 +843,12 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A Flush(); } + #ifdef _DEBUG + AString DecryptedKeyHex; + CreateHexDump(DecryptedKeyHex, DecryptedKey, res, 16); + LOGD("Received encryption key, %d bytes:\n%s", res, DecryptedKeyHex.c_str()); + #endif + StartEncryption(DecryptedKey); return; } @@ -940,21 +857,21 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A -void cProtocol132::StartEncryption(const byte * a_Key) +void cProtocol132::StartEncryption(const Byte * a_Key) { - m_Encryptor.SetKey(a_Key, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(a_Key, 16))(Name::FeedbackSize(), 1)); - m_Decryptor.SetKey(a_Key, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(a_Key, 16))(Name::FeedbackSize(), 1)); + m_Encryptor.Init(a_Key, a_Key); + m_Decryptor.Init(a_Key, a_Key); m_IsEncrypted = true; // Prepare the m_AuthServerID: - CryptoPP::SHA1 Checksum; + cSHA1Checksum Checksum; AString ServerID = cRoot::Get()->GetServer()->GetServerID(); - Checksum.Update((const byte *)ServerID.c_str(), ServerID.length()); + Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length()); Checksum.Update(a_Key, 16); - Checksum.Update((const byte *)m_ServerPublicKey.c_str(), m_ServerPublicKey.length()); - byte Digest[20]; - Checksum.Final(Digest); - DigestToJava(Digest, m_AuthServerID); + Checksum.Update((const Byte *)cRoot::Get()->GetServer()->GetPublicKeyDER().data(), cRoot::Get()->GetServer()->GetPublicKeyDER().size()); + Byte Digest[20]; + Checksum.Finalize(Digest); + cSHA1Checksum::DigestToJava(Digest, m_AuthServerID); } diff --git a/src/Protocol/Protocol132.h b/src/Protocol/Protocol132.h index 80fc8740a..89f4636f5 100644 --- a/src/Protocol/Protocol132.h +++ b/src/Protocol/Protocol132.h @@ -20,13 +20,12 @@ #pragma warning(disable:4702) #endif -#include "cryptopp/modes.h" -#include "cryptopp/aes.h" - #ifdef _MSC_VER #pragma warning(pop) #endif +#include "../Crypto.h" + @@ -79,16 +78,15 @@ public: protected: bool m_IsEncrypted; - CryptoPP::CFB_Mode::Decryption m_Decryptor; - CryptoPP::CFB_Mode::Encryption m_Encryptor; + + cAESCFBDecryptor m_Decryptor; + cAESCFBEncryptor m_Encryptor; + AString m_DataToSend; /// The ServerID used for session authentication; set in StartEncryption(), used in GetAuthServerID() AString m_AuthServerID; - /// The server's public key, as used by SendEncryptionKeyRequest() and StartEncryption() - AString m_ServerPublicKey; - virtual void SendData(const char * a_Data, int a_Size) override; // DEBUG: @@ -108,7 +106,7 @@ protected: void HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce); /// Starts the symmetric encryption with the specified key; also sets m_AuthServerID - void StartEncryption(const byte * a_Key); + void StartEncryption(const Byte * a_Key); } ; diff --git a/src/Protocol/Protocol14x.cpp b/src/Protocol/Protocol14x.cpp index 127ce9d4b..f82e6de45 100644 --- a/src/Protocol/Protocol14x.cpp +++ b/src/Protocol/Protocol14x.cpp @@ -33,8 +33,6 @@ Implements the 1.4.x protocol classes representing these protocols: #pragma warning(disable:4702) #endif -#include "cryptopp/randpool.h" - #ifdef _MSC_VER #pragma warning(pop) #endif diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 9506332dc..bcc638796 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -73,11 +73,11 @@ void cProtocol172::DataReceived(const char * a_Data, int a_Size) { if (m_IsEncrypted) { - byte Decrypted[512]; + Byte Decrypted[512]; while (a_Size > 0) { int NumBytes = (a_Size > sizeof(Decrypted)) ? sizeof(Decrypted) : a_Size; - m_Decryptor.ProcessData(Decrypted, (byte *)a_Data, NumBytes); + m_Decryptor.ProcessData(Decrypted, (Byte *)a_Data, NumBytes); AddReceivedData((const char *)Decrypted, NumBytes); a_Size -= NumBytes; a_Data += NumBytes; @@ -1664,11 +1664,11 @@ void cProtocol172::SendData(const char * a_Data, int a_Size) { if (m_IsEncrypted) { - byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks) + Byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks) while (a_Size > 0) { int NumBytes = (a_Size > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Size; - m_Encryptor.ProcessData(Encrypted, (byte *)a_Data, NumBytes); + m_Encryptor.ProcessData(Encrypted, (Byte *)a_Data, NumBytes); m_Client->SendData((const char *)Encrypted, NumBytes); a_Size -= NumBytes; a_Data += NumBytes; diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 3f440f313..0617b6c00 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -26,21 +26,20 @@ Declares the 1.7.x protocol classes: #pragma warning(disable:4702) #endif -#include "cryptopp/modes.h" -#include "cryptopp/aes.h" - #ifdef _MSC_VER #pragma warning(pop) #endif +#include "../Crypto.h" + class cProtocol172 : - public cProtocol // TODO + public cProtocol { - typedef cProtocol super; // TODO + typedef cProtocol super; public: @@ -220,9 +219,9 @@ protected: cByteBuffer m_OutPacketLenBuffer; bool m_IsEncrypted; - CryptoPP::CFB_Mode::Decryption m_Decryptor; - CryptoPP::CFB_Mode::Encryption m_Encryptor; + cAESCFBDecryptor m_Decryptor; + cAESCFBEncryptor m_Encryptor; /// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets void AddReceivedData(const char * a_Data, int a_Size); diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index de5dd3fb9..32409c2aa 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -965,7 +965,7 @@ void cProtocolRecognizer::SendLengthlessServerPing(void) m_Buffer.ResetRead(); if (m_Buffer.CanReadBytes(2)) { - byte val; + Byte val; m_Buffer.ReadByte(val); // Packet type - Serverlist ping m_Buffer.ReadByte(val); // 0x01 magic value ASSERT(val == 0x01); diff --git a/src/Server.cpp b/src/Server.cpp index 34ee066cb..f64af62eb 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -284,17 +284,9 @@ int cServer::GetNumPlayers(void) void cServer::PrepareKeys(void) { - // TODO: Save and load key for persistence across sessions - // But generating the key takes only a moment, do we even need that? - LOGD("Generating protocol encryption keypair..."); - - time_t CurTime = time(NULL); - CryptoPP::RandomPool rng; - rng.Put((const byte *)&CurTime, sizeof(CurTime)); - m_PrivateKey.GenerateRandomWithKeySize(rng, 1024); - CryptoPP::RSA::PublicKey pk(m_PrivateKey); - m_PublicKey = pk; + VERIFY(m_PrivateKey.Generate(1024)); + m_PublicKeyDER = m_PrivateKey.GetPubKeyDER(); } diff --git a/src/Server.h b/src/Server.h index bb55e81b6..15eafc00a 100644 --- a/src/Server.h +++ b/src/Server.h @@ -23,8 +23,7 @@ #pragma warning(disable:4702) #endif -#include "cryptopp/rsa.h" -#include "cryptopp/randpool.h" +#include "Crypto.h" #ifdef _MSC_VER #pragma warning(pop) @@ -110,8 +109,8 @@ public: // tolua_export /** Returns base64 encoded favicon data (obtained from favicon.png) */ const AString & GetFaviconData(void) const { return m_FaviconData; } - CryptoPP::RSA::PrivateKey & GetPrivateKey(void) { return m_PrivateKey; } - CryptoPP::RSA::PublicKey & GetPublicKey (void) { return m_PublicKey; } + cRSAPrivateKey & GetPrivateKey(void) { return m_PrivateKey; } + const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; } private: @@ -180,8 +179,11 @@ private: bool m_bRestarting; - CryptoPP::RSA::PrivateKey m_PrivateKey; - CryptoPP::RSA::PublicKey m_PublicKey; + /** The private key used for the assymetric encryption start in the protocols */ + cRSAPrivateKey m_PrivateKey; + + /** Public key for m_PrivateKey, ASN1-DER-encoded */ + AString m_PublicKeyDER; cRCONServer m_RCONServer; -- cgit v1.2.3 From e251e526739b72554b99260e047727d1e85aadf9 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 23 Jan 2014 23:45:28 +0100 Subject: Fixed a warning in ScoreboardSerializer. --- src/WorldStorage/ScoreboardSerializer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp index dabc5e2e1..0788aff17 100644 --- a/src/WorldStorage/ScoreboardSerializer.cpp +++ b/src/WorldStorage/ScoreboardSerializer.cpp @@ -321,13 +321,13 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) CurrLine = a_NBT.FindChildByName(Child, "AllowFriendlyFire"); if (CurrLine >= 0) { - AllowsFriendlyFire = a_NBT.GetInt(CurrLine); + AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0); } CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles"); if (CurrLine >= 0) { - CanSeeFriendlyInvisible = a_NBT.GetInt(CurrLine); + CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0); } cTeam * Team = m_ScoreBoard->RegisterTeam(Name, DisplayName, Prefix, Suffix); -- cgit v1.2.3 From 11948b1d4b98e0147217eef2928a2391c2d8e958 Mon Sep 17 00:00:00 2001 From: Mike Hunsinger Date: Thu, 23 Jan 2014 19:54:00 -0700 Subject: Fixed spacing and doxycomments. --- src/Entities/Player.cpp | 6 +++--- src/Entities/Player.h | 6 +++--- src/UI/Window.cpp | 22 ++++++++++------------ 3 files changed, 16 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index ca39d4d9d..64cd334d1 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1389,8 +1389,8 @@ void cPlayer::TossHeldItem(char a_Amount) } } - double vX = 0, vY = 0, vZ = 0; - EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); + double vX = 0, vY = 0, vZ = 0; + EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); vY = -vY * 2 + 1.f; m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player } @@ -1402,7 +1402,7 @@ void cPlayer::TossHeldItem(char a_Amount) void cPlayer::TossPickup(const cItem & a_Item) { cItems Drops; - Drops.push_back(a_Item); + Drops.push_back(a_Item); double vX = 0, vY = 0, vZ = 0; EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 71033ab77..7925e70a1 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -214,13 +214,13 @@ public: /// Returns the full color code to use for this player, based on their primary group or set in m_Color AString GetColor(void) const; - // tosses the item in the selected hotbar slot + /** tosses the item in the selected hotbar slot */ void TossEquippedItem(char a_Amount = 1); - // tosses the item held in hand (when in UI windows) + /** tosses the item held in hand (when in UI windows) */ void TossHeldItem(char a_Amount = 1); - // tosses a pickup newly created from a_Item + /** tosses a pickup newly created from a_Item */ void TossPickup(const cItem & a_Item); /// Heals the player by the specified amount of HPs (positive only); sends health update diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp index 3d23dfd07..4261a58d9 100644 --- a/src/UI/Window.cpp +++ b/src/UI/Window.cpp @@ -171,7 +171,6 @@ void cWindow::Clicked( ) { cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); - if (a_WindowID != m_WindowID) { LOGWARNING("%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__, m_WindowID, a_WindowID, a_Player.GetName().c_str()); @@ -182,16 +181,15 @@ void cWindow::Clicked( { case caRightClickOutside: { - if (PlgMgr->CallHookPlayerTossingItem(a_Player)) + if (PlgMgr->CallHookPlayerTossingItem(a_Player)) { // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } - - if (a_Player.IsGameModeCreative()) - { - a_Player.TossPickup(a_ClickedItem); - } + if (a_Player.IsGameModeCreative()) + { + a_Player.TossPickup(a_ClickedItem); + } // Toss one of the dragged items: a_Player.TossHeldItem(); @@ -205,10 +203,10 @@ void cWindow::Clicked( return; } - if (a_Player.IsGameModeCreative()) - { - a_Player.TossPickup(a_ClickedItem); - } + if (a_Player.IsGameModeCreative()) + { + a_Player.TossPickup(a_ClickedItem); + } // Toss all dragged items: a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); @@ -288,7 +286,7 @@ bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) if (a_Player.IsDraggingItem()) { LOGD("Player holds item! Dropping it..."); - a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); + a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } cClientHandle * ClientHandle = a_Player.GetClientHandle(); -- cgit v1.2.3 From 9926ea58e841af94ded4ea55e409020c732f6cb7 Mon Sep 17 00:00:00 2001 From: Mike Hunsinger Date: Thu, 23 Jan 2014 20:01:08 -0700 Subject: Fixed indentation and doxygen comments... For real this time. --- src/Entities/Player.cpp | 6 +++--- src/UI/Window.cpp | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 64cd334d1..54de4dee9 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1389,8 +1389,8 @@ void cPlayer::TossHeldItem(char a_Amount) } } - double vX = 0, vY = 0, vZ = 0; - EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); + double vX = 0, vY = 0, vZ = 0; + EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); vY = -vY * 2 + 1.f; m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player } @@ -1402,7 +1402,7 @@ void cPlayer::TossHeldItem(char a_Amount) void cPlayer::TossPickup(const cItem & a_Item) { cItems Drops; - Drops.push_back(a_Item); + Drops.push_back(a_Item); double vX = 0, vY = 0, vZ = 0; EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp index 4261a58d9..dd058b304 100644 --- a/src/UI/Window.cpp +++ b/src/UI/Window.cpp @@ -170,7 +170,7 @@ void cWindow::Clicked( const cItem & a_ClickedItem ) { - cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); + cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); if (a_WindowID != m_WindowID) { LOGWARNING("%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__, m_WindowID, a_WindowID, a_Player.GetName().c_str()); @@ -181,15 +181,15 @@ void cWindow::Clicked( { case caRightClickOutside: { - if (PlgMgr->CallHookPlayerTossingItem(a_Player)) + if (PlgMgr->CallHookPlayerTossingItem(a_Player)) { // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } - if (a_Player.IsGameModeCreative()) - { - a_Player.TossPickup(a_ClickedItem); - } + if (a_Player.IsGameModeCreative()) + { + a_Player.TossPickup(a_ClickedItem); + } // Toss one of the dragged items: a_Player.TossHeldItem(); @@ -203,10 +203,10 @@ void cWindow::Clicked( return; } - if (a_Player.IsGameModeCreative()) - { - a_Player.TossPickup(a_ClickedItem); - } + if (a_Player.IsGameModeCreative()) + { + a_Player.TossPickup(a_ClickedItem); + } // Toss all dragged items: a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); @@ -285,8 +285,8 @@ bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) // Checks whether the player is still holding an item if (a_Player.IsDraggingItem()) { - LOGD("Player holds item! Dropping it..."); - a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); + LOGD("Player holds item! Dropping it..."); + a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } cClientHandle * ClientHandle = a_Player.GetClientHandle(); -- cgit v1.2.3 From 7c12247263502030fbf50fc6fda12bb8f67a269b Mon Sep 17 00:00:00 2001 From: Mike Hunsinger Date: Thu, 23 Jan 2014 20:11:10 -0700 Subject: Fixed indentation once and for all. --- src/Entities/Player.cpp | 62 ++++++++++++++++++++++++------------------------- src/UI/Window.cpp | 30 ++++++++++++------------ 2 files changed, 46 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 54de4dee9..b2574c433 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1345,20 +1345,20 @@ AString cPlayer::GetColor(void) const void cPlayer::TossEquippedItem(char a_Amount) { cItems Drops; - cItem DroppedItem(GetInventory().GetEquippedItem()); - if (!DroppedItem.IsEmpty()) - { - char NewAmount = a_Amount; - if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount) - { - NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there - } + cItem DroppedItem(GetInventory().GetEquippedItem()); + if (!DroppedItem.IsEmpty()) + { + char NewAmount = a_Amount; + if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount) + { + NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there + } - GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount); + GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount); - DroppedItem.m_ItemCount = NewAmount; - Drops.push_back(DroppedItem); - } + DroppedItem.m_ItemCount = NewAmount; + Drops.push_back(DroppedItem); + } double vX = 0, vY = 0, vZ = 0; EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); @@ -1373,24 +1373,24 @@ void cPlayer::TossEquippedItem(char a_Amount) void cPlayer::TossHeldItem(char a_Amount) { cItems Drops; - cItem & Item = GetDraggingItem(); - if (!Item.IsEmpty()) - { - char OriginalItemAmount = Item.m_ItemCount; - Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount); - Drops.push_back(Item); - if (OriginalItemAmount > a_Amount) - { - Item.m_ItemCount = OriginalItemAmount - a_Amount; - } - else - { - Item.Empty(); - } - } - - double vX = 0, vY = 0, vZ = 0; - EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); + cItem & Item = GetDraggingItem(); + if (!Item.IsEmpty()) + { + char OriginalItemAmount = Item.m_ItemCount; + Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount); + Drops.push_back(Item); + if (OriginalItemAmount > a_Amount) + { + Item.m_ItemCount = OriginalItemAmount - a_Amount; + } + else + { + Item.Empty(); + } + } + + double vX = 0, vY = 0, vZ = 0; + EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); vY = -vY * 2 + 1.f; m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player } @@ -1402,7 +1402,7 @@ void cPlayer::TossHeldItem(char a_Amount) void cPlayer::TossPickup(const cItem & a_Item) { cItems Drops; - Drops.push_back(a_Item); + Drops.push_back(a_Item); double vX = 0, vY = 0, vZ = 0; EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp index dd058b304..1a8456f70 100644 --- a/src/UI/Window.cpp +++ b/src/UI/Window.cpp @@ -181,15 +181,15 @@ void cWindow::Clicked( { case caRightClickOutside: { - if (PlgMgr->CallHookPlayerTossingItem(a_Player)) + if (PlgMgr->CallHookPlayerTossingItem(a_Player)) + { + // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) + return; + } + if (a_Player.IsGameModeCreative()) { - // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) - return; + a_Player.TossPickup(a_ClickedItem); } - if (a_Player.IsGameModeCreative()) - { - a_Player.TossPickup(a_ClickedItem); - } // Toss one of the dragged items: a_Player.TossHeldItem(); @@ -199,14 +199,14 @@ void cWindow::Clicked( { if (PlgMgr->CallHookPlayerTossingItem(a_Player)) { - // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) - return; + // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) + return; } - if (a_Player.IsGameModeCreative()) - { - a_Player.TossPickup(a_ClickedItem); - } + if (a_Player.IsGameModeCreative()) + { + a_Player.TossPickup(a_ClickedItem); + } // Toss all dragged items: a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); @@ -285,8 +285,8 @@ bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) // Checks whether the player is still holding an item if (a_Player.IsDraggingItem()) { - LOGD("Player holds item! Dropping it..."); - a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); + LOGD("Player holds item! Dropping it..."); + a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } cClientHandle * ClientHandle = a_Player.GetClientHandle(); -- cgit v1.2.3 From 22d101034ffe810297455fb4caa27baf138a6342 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 23 Jan 2014 22:24:20 +0100 Subject: Fixed flint&steel failure on the Y world edges. --- src/Items/ItemLighter.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/Items/ItemLighter.h b/src/Items/ItemLighter.h index 4281a2d0c..8f3389d95 100644 --- a/src/Items/ItemLighter.h +++ b/src/Items/ItemLighter.h @@ -42,6 +42,10 @@ public: { // Light a fire next to/on top of the block if air: AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) + { + break; + } if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR) { a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0); -- cgit v1.2.3 From b02940209d64e4239ac6c0e7c8cb4f1d8280b7aa Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 24 Jan 2014 09:57:12 +0100 Subject: Fixed crash with failed entity-loading. This should fix issues reported in: http://forum.mc-server.org/showthread.php?tid=1328 http://forum.mc-server.org/showthread.php?tid=1308 --- src/Entities/Entity.cpp | 3 ++- src/WorldStorage/WSSAnvil.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 565c78dfd..09fb7052d 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -73,7 +73,8 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d cEntity::~cEntity() { - ASSERT(!m_World->HasEntity(m_UniqueID)); // Before deleting, the entity needs to have been removed from the world + // Before deleting, the entity needs to have been removed from the world, if ever added + ASSERT((m_World == NULL) || !m_World->HasEntity(m_UniqueID)); /* // DEBUG: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 8be6372e2..e2a882f65 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1926,14 +1926,19 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N double Speed[3]; if (!LoadDoublesListFromNBT(Speed, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Motion"))) { - return false; + // Provide default speed: + Speed[0] = 0; + Speed[1] = 0; + Speed[2] = 0; } a_Entity.SetSpeed(Speed[0], Speed[1], Speed[2]); double Rotation[3]; if (!LoadDoublesListFromNBT(Rotation, 2, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Rotation"))) { - return false; + // Provide default rotation: + Rotation[0] = 0; + Rotation[1] = 0; } a_Entity.SetYaw(Rotation[0]); a_Entity.SetRoll(Rotation[1]); -- cgit v1.2.3 From 0369c585fb16777acd4639122f8cee2d7c60833d Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 24 Jan 2014 09:58:40 +0100 Subject: Fixed a few compile-time and runtime warnings in ScoreboardSerializer. --- src/WorldStorage/ScoreboardSerializer.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp index a53971dc2..c65e13f98 100644 --- a/src/WorldStorage/ScoreboardSerializer.cpp +++ b/src/WorldStorage/ScoreboardSerializer.cpp @@ -31,16 +31,12 @@ cScoreboardSerializer::cScoreboardSerializer(const AString & a_WorldName, cScore bool cScoreboardSerializer::Load(void) { - cFile File; - if (!File.Open(FILE_IO_PREFIX + m_Path, cFile::fmRead)) + AString Data = cFile::ReadWholeFile(FILE_IO_PREFIX + m_Path); + if (Data.empty()) { return false; } - AString Data; - File.ReadRestOfFile(Data); - File.Close(); - AString Uncompressed; int res = UncompressStringGZIP(Data.data(), Data.size(), Uncompressed); @@ -313,13 +309,13 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) CurrLine = a_NBT.FindChildByName(Child, "AllowFriendlyFire"); if (CurrLine >= 0) { - AllowsFriendlyFire = a_NBT.GetInt(CurrLine); + AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0); } CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles"); if (CurrLine >= 0) { - CanSeeFriendlyInvisible = a_NBT.GetInt(CurrLine); + CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0); } cTeam * Team = m_ScoreBoard->RegisterTeam(Name, DisplayName, Prefix, Suffix); -- cgit v1.2.3 From e75f979e01b34fbd1a2993be9fd4aa7211da26cf Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 24 Jan 2014 10:24:24 +0100 Subject: Fixed Win nightbuilds not producing PDBs. --- src/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 51182d3bc..a8cc0530d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -134,6 +134,13 @@ else () "StackWalker.cpp LeakFinder.h" PROPERTIES COMPILE_FLAGS "/Yc\"Globals.h\"" ) list(APPEND SOURCE "Resources/MCServer.rc") + + # Make MSVC generate the PDB files even for the release build: + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") + set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /DEBUG") endif() set(EXECUTABLE MCServer) -- cgit v1.2.3 From f39daabf7eb4f54bda0f6385aff75dd4f22f75ca Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 19:39:39 +0000 Subject: Added more minecart powered rail directions --- src/Entities/Minecart.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++--- src/ReferenceManager.cpp | 43 ------------------------------ src/ReferenceManager.h | 34 ------------------------ 3 files changed, 63 insertions(+), 80 deletions(-) delete mode 100644 src/ReferenceManager.cpp delete mode 100644 src/ReferenceManager.h (limited to 'src') diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 6477fb1ca..78ec017cd 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -474,7 +474,7 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) } break; } - case E_META_RAIL_ASCEND_XM: + case E_META_RAIL_ASCEND_XM: // ASCEND EAST { SetYaw(180); SetSpeedZ(0); @@ -483,16 +483,76 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) { if (GetSpeedX() <= MAX_SPEED) { - AddSpeedX(1); + AddSpeedX(AccelDecelSpeed); SetSpeedY(-GetSpeedX()); } } else { - AddSpeedX(-1); + AddSpeedX(AccelDecelNegSpeed); SetSpeedY(-GetSpeedX()); } break; + } + case E_META_RAIL_ASCEND_XP: // ASCEND WEST + { + SetYaw(180); + SetSpeedZ(0); + + if (GetSpeedX() > 0) + { + AddSpeedX(AccelDecelSpeed); + SetSpeedY(GetSpeedX()); + } + else + { + if (GetSpeedX() >= MAX_SPEED_NEGATIVE) + { + AddSpeedX(AccelDecelNegSpeed); + SetSpeedY(GetSpeedX()); + } + } + break; + } + case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH + { + SetYaw(270); + SetSpeedX(0); + + if (GetSpeedZ() >= 0) + { + if (GetSpeedZ() <= MAX_SPEED) + { + AddSpeedZ(AccelDecelSpeed); + SetSpeedY(-GetSpeedZ()); + } + } + else + { + AddSpeedZ(AccelDecelNegSpeed); + SetSpeedY(-GetSpeedZ()); + } + break; + } + case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH + { + SetYaw(270); + SetSpeedX(0); + + if (GetSpeedZ() > 0) + { + AddSpeedZ(AccelDecelSpeed); + SetSpeedY(GetSpeedZ()); + } + else + { + if (GetSpeedZ() >= MAX_SPEED_NEGATIVE) + { + AddSpeedZ(AccelDecelNegSpeed); + SetSpeedY(GetSpeedZ()); + } + } + break; } default: ASSERT(!"Unhandled powered rail metadata!"); break; } diff --git a/src/ReferenceManager.cpp b/src/ReferenceManager.cpp deleted file mode 100644 index 6a9ed0e43..000000000 --- a/src/ReferenceManager.cpp +++ /dev/null @@ -1,43 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "ReferenceManager.h" -#include "Entities/Entity.h" - - - - - -cReferenceManager::cReferenceManager( ENUM_REFERENCE_MANAGER_TYPE a_Type ) - : m_Type( a_Type ) -{ -} - -cReferenceManager::~cReferenceManager() -{ - if( m_Type == RFMNGR_REFERENCERS ) - { - for( std::list< cEntity** >::iterator itr = m_References.begin(); itr != m_References.end(); ++itr ) - { - *(*itr) = 0; // Set referenced pointer to 0 - } - } - else - { - for( std::list< cEntity** >::iterator itr = m_References.begin(); itr != m_References.end(); ++itr ) - { - cEntity* Ptr = (*(*itr)); - if( Ptr ) Ptr->Dereference( *(*itr) ); - } - } -} - -void cReferenceManager::AddReference( cEntity*& a_EntityPtr ) -{ - m_References.push_back( &a_EntityPtr ); -} - -void cReferenceManager::Dereference( cEntity*& a_EntityPtr ) -{ - m_References.remove( &a_EntityPtr ); -} \ No newline at end of file diff --git a/src/ReferenceManager.h b/src/ReferenceManager.h deleted file mode 100644 index bcd451f72..000000000 --- a/src/ReferenceManager.h +++ /dev/null @@ -1,34 +0,0 @@ - -#pragma once - - - - - -class cEntity; - - - - - -class cReferenceManager -{ -public: - enum ENUM_REFERENCE_MANAGER_TYPE - { - RFMNGR_REFERENCERS, - RFMNGR_REFERENCES, - }; - cReferenceManager( ENUM_REFERENCE_MANAGER_TYPE a_Type ); - ~cReferenceManager(); - - void AddReference( cEntity*& a_EntityPtr ); - void Dereference( cEntity*& a_EntityPtr ); -private: - ENUM_REFERENCE_MANAGER_TYPE m_Type; - std::list< cEntity** > m_References; -}; - - - - -- cgit v1.2.3 From 2ce26574efa89a5709f121acdf289ad3366d3881 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 19:46:45 +0000 Subject: Removed unused ReferenceManager --- src/Entities/Entity.cpp | 36 ------------------------------------ src/Entities/Entity.h | 10 +--------- src/ReferenceManager.cpp | 43 ------------------------------------------- src/ReferenceManager.h | 34 ---------------------------------- 4 files changed, 1 insertion(+), 122 deletions(-) delete mode 100644 src/ReferenceManager.cpp delete mode 100644 src/ReferenceManager.h (limited to 'src') diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 09fb7052d..ae98a1e91 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -4,9 +4,7 @@ #include "../World.h" #include "../Server.h" #include "../Root.h" -#include "../Vector3d.h" #include "../Matrix4f.h" -#include "../ReferenceManager.h" #include "../ClientHandle.h" #include "../Chunk.h" #include "../Simulator/FluidSimulator.h" @@ -32,8 +30,6 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d , m_MaxHealth(1) , m_AttachedTo(NULL) , m_Attachee(NULL) - , m_Referencers(new cReferenceManager(cReferenceManager::RFMNGR_REFERENCERS)) - , m_References(new cReferenceManager(cReferenceManager::RFMNGR_REFERENCES)) , m_bDirtyHead(true) , m_bDirtyOrientation(true) , m_bDirtyPosition(true) @@ -100,8 +96,6 @@ cEntity::~cEntity() LOGWARNING("ERROR: Entity deallocated without being destroyed"); ASSERT(!"Entity deallocated without being destroyed or unlinked"); } - delete m_Referencers; - delete m_References; } @@ -1430,33 +1424,3 @@ void cEntity::SetPosZ(double a_PosZ) - -////////////////////////////////////////////////////////////////////////// -// Reference stuffs -void cEntity::AddReference(cEntity * & a_EntityPtr) -{ - m_References->AddReference(a_EntityPtr); - a_EntityPtr->ReferencedBy(a_EntityPtr); -} - - - - - -void cEntity::ReferencedBy(cEntity * & a_EntityPtr) -{ - m_Referencers->AddReference(a_EntityPtr); -} - - - - - -void cEntity::Dereference(cEntity * & a_EntityPtr) -{ - m_Referencers->Dereference(a_EntityPtr); -} - - - - diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 91463bfd6..62dc42c3f 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -4,6 +4,7 @@ #include "../Item.h" #include "../Vector3d.h" #include "../Vector3f.h" +#include "../Vector3i.h" @@ -33,7 +34,6 @@ class cWorld; -class cReferenceManager; class cClientHandle; class cPlayer; class cChunk; @@ -373,9 +373,6 @@ protected: /// The entity which is attached to this entity (rider), NULL if none cEntity * m_Attachee; - cReferenceManager* m_Referencers; - cReferenceManager* m_References; - // Flags that signal that we haven't updated the clients with the latest. bool m_bDirtyHead; bool m_bDirtyOrientation; @@ -416,11 +413,6 @@ protected: void SetWorld(cWorld * a_World) { m_World = a_World; } - friend class cReferenceManager; - void AddReference( cEntity*& a_EntityPtr ); - void ReferencedBy( cEntity*& a_EntityPtr ); - void Dereference( cEntity*& a_EntityPtr ); - private: // Measured in degrees, [-180, +180) double m_HeadYaw; diff --git a/src/ReferenceManager.cpp b/src/ReferenceManager.cpp deleted file mode 100644 index 6a9ed0e43..000000000 --- a/src/ReferenceManager.cpp +++ /dev/null @@ -1,43 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "ReferenceManager.h" -#include "Entities/Entity.h" - - - - - -cReferenceManager::cReferenceManager( ENUM_REFERENCE_MANAGER_TYPE a_Type ) - : m_Type( a_Type ) -{ -} - -cReferenceManager::~cReferenceManager() -{ - if( m_Type == RFMNGR_REFERENCERS ) - { - for( std::list< cEntity** >::iterator itr = m_References.begin(); itr != m_References.end(); ++itr ) - { - *(*itr) = 0; // Set referenced pointer to 0 - } - } - else - { - for( std::list< cEntity** >::iterator itr = m_References.begin(); itr != m_References.end(); ++itr ) - { - cEntity* Ptr = (*(*itr)); - if( Ptr ) Ptr->Dereference( *(*itr) ); - } - } -} - -void cReferenceManager::AddReference( cEntity*& a_EntityPtr ) -{ - m_References.push_back( &a_EntityPtr ); -} - -void cReferenceManager::Dereference( cEntity*& a_EntityPtr ) -{ - m_References.remove( &a_EntityPtr ); -} \ No newline at end of file diff --git a/src/ReferenceManager.h b/src/ReferenceManager.h deleted file mode 100644 index bcd451f72..000000000 --- a/src/ReferenceManager.h +++ /dev/null @@ -1,34 +0,0 @@ - -#pragma once - - - - - -class cEntity; - - - - - -class cReferenceManager -{ -public: - enum ENUM_REFERENCE_MANAGER_TYPE - { - RFMNGR_REFERENCERS, - RFMNGR_REFERENCES, - }; - cReferenceManager( ENUM_REFERENCE_MANAGER_TYPE a_Type ); - ~cReferenceManager(); - - void AddReference( cEntity*& a_EntityPtr ); - void Dereference( cEntity*& a_EntityPtr ); -private: - ENUM_REFERENCE_MANAGER_TYPE m_Type; - std::list< cEntity** > m_References; -}; - - - - -- cgit v1.2.3 From 3e675f8c38720cd6c483ee0f9733a9c060ded936 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 19:52:52 +0000 Subject: Implemented creeper abilities * Creepers now explode with a sound effect * Creepers drop a music disc on the unlikely event of being killed by a skeleton's arrow Inspired by @maniak89's PR #132. --- src/Mobs/Creeper.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- src/Mobs/Creeper.h | 3 +++ 2 files changed, 50 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Mobs/Creeper.cpp b/src/Mobs/Creeper.cpp index 4e11ae13e..ad8fe10a1 100644 --- a/src/Mobs/Creeper.cpp +++ b/src/Mobs/Creeper.cpp @@ -3,6 +3,7 @@ #include "Creeper.h" #include "../World.h" +#include "../Entities/ProjectileEntity.h" @@ -11,7 +12,8 @@ cCreeper::cCreeper(void) : super("Creeper", mtCreeper, "mob.creeper.say", "mob.creeper.say", 0.6, 1.8), m_bIsBlowing(false), - m_bIsCharged(false) + m_bIsCharged(false), + m_ExplodingTimer(0) { } @@ -19,11 +21,34 @@ cCreeper::cCreeper(void) : +void cCreeper::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + if (!ReachedFinalDestination()) + { + m_ExplodingTimer = 0; + m_bIsBlowing = false; + m_World->BroadcastEntityMetadata(*this); + } +} + + + + + void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer) { AddRandomDropItem(a_Drops, 0, 2, E_ITEM_GUNPOWDER); - // TODO Check if killed by a skeleton, then drop random music disk + if ((a_Killer != NULL) && (a_Killer->IsProjectile())) + { + if (((cMonster *)((cProjectileEntity *)a_Killer)->GetCreator())->GetMobType() == mtSkeleton) + { + // 12 music discs. TickRand starts from 0, so range = 11. Disk IDs start at 2256, so add that. There. + AddRandomDropItem(a_Drops, 1, 1, (short)m_World->GetTickRandomNumber(11) + 2256); + } + } } @@ -45,3 +70,23 @@ void cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI) + +void cCreeper::Attack(float a_Dt) +{ + UNUSED(a_Dt); + + m_ExplodingTimer += 1; + + if (!m_bIsBlowing) + { + m_World->BroadcastSoundEffect("random.fuse", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); + m_bIsBlowing = true; + m_World->BroadcastEntityMetadata(*this); + } + + if (m_ExplodingTimer == 20) + { + m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this); + Destroy(); + } +} \ No newline at end of file diff --git a/src/Mobs/Creeper.h b/src/Mobs/Creeper.h index c3d4edeae..0f71e5ad2 100644 --- a/src/Mobs/Creeper.h +++ b/src/Mobs/Creeper.h @@ -19,6 +19,8 @@ public: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual void Attack(float a_Dt) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; bool IsBlowing(void) const {return m_bIsBlowing; } bool IsCharged(void) const {return m_bIsCharged; } @@ -26,6 +28,7 @@ public: private: bool m_bIsBlowing, m_bIsCharged; + int m_ExplodingTimer; } ; -- cgit v1.2.3 From 161a1c72745fcb9274483d75af5238a6b7740ba3 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 19:54:13 +0000 Subject: Fixed mobs too close to player not ticking A condition would never be fulfilled. A number squared was compared to -1, but there is nothing that, multiplied by itself, gives -1. --- src/MobProximityCounter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/MobProximityCounter.cpp b/src/MobProximityCounter.cpp index 583a71579..6c44ea458 100644 --- a/src/MobProximityCounter.cpp +++ b/src/MobProximityCounter.cpp @@ -59,7 +59,7 @@ cMobProximityCounter::sIterablePair cMobProximityCounter::getMobWithinThosesDist { if (toReturn.m_Begin == m_DistanceToMonster.end()) { - if (a_DistanceMin == -1 || itr->first > a_DistanceMin) + if ((a_DistanceMin == 1) || (itr->first > a_DistanceMin)) { toReturn.m_Begin = itr; // this is the first one with distance > a_DistanceMin; } @@ -67,7 +67,7 @@ cMobProximityCounter::sIterablePair cMobProximityCounter::getMobWithinThosesDist if (toReturn.m_Begin != m_DistanceToMonster.end()) { - if (a_DistanceMax != -1 && itr->first > a_DistanceMax) + if ((a_DistanceMax != 1) && (itr->first > a_DistanceMax)) { toReturn.m_End = itr; // this is just after the last one with distance < a_DistanceMax // Note : if we are not going through this, it's ok, toReturn.m_End will be end(); -- cgit v1.2.3 From 9c0e3615ce61dba0ae973b97807833bd6ddd5bda Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 19:57:32 +0000 Subject: Large reworking of mob code [SEE DESC] + Implemented better pathfinding - Removed lots of unused variables, functions, etc. * Changed some variable types * Other miscellaneous fixes, and also completes the previous PRs --- src/Mobs/AggressiveMonster.cpp | 65 ++++--- src/Mobs/AggressiveMonster.h | 5 +- src/Mobs/Monster.cpp | 400 ++++++++++++++++++++++++----------------- src/Mobs/Monster.h | 68 +++++-- src/Mobs/PassiveMonster.cpp | 16 +- src/Mobs/Wolf.cpp | 2 +- src/MonsterConfig.cpp | 20 +-- 7 files changed, 334 insertions(+), 242 deletions(-) (limited to 'src') diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp index cc7e7da2b..a4b3eede1 100644 --- a/src/Mobs/AggressiveMonster.cpp +++ b/src/Mobs/AggressiveMonster.cpp @@ -4,7 +4,6 @@ #include "AggressiveMonster.h" #include "../World.h" -#include "../Vector3f.h" #include "../Entities/Player.h" #include "../MersenneTwister.h" @@ -13,8 +12,7 @@ cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : - super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height), - m_ChaseTime(999999) + super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height) { m_EMPersonality = AGGRESSIVE; } @@ -27,32 +25,23 @@ cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eType a_Mob void cAggressiveMonster::InStateChasing(float a_Dt) { super::InStateChasing(a_Dt); - m_ChaseTime += a_Dt; + if (m_Target != NULL) { if (m_Target->IsPlayer()) { - cPlayer * Player = (cPlayer *) m_Target; - if (Player->IsGameModeCreative()) + if (((cPlayer *)m_Target)->IsGameModeCreative()) { m_EMState = IDLE; return; } } - Vector3f Pos = Vector3f( GetPosition() ); - Vector3f Their = Vector3f( m_Target->GetPosition() ); - if ((Their - Pos).Length() <= m_AttackRange) + if (((float)m_FinalDestination.x != (float)m_Target->GetPosX()) || ((float)m_FinalDestination.z != (float)m_Target->GetPosZ())) { - Attack(a_Dt); + MoveToPosition(m_Target->GetPosition()); } - MoveToPosition(Their + Vector3f(0, 0.65f, 0)); } - else if (m_ChaseTime > 5.f) - { - m_ChaseTime = 0; - m_EMState = IDLE; - } } @@ -62,7 +51,10 @@ void cAggressiveMonster::InStateChasing(float a_Dt) void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity) { super::EventSeePlayer(a_Entity); - m_EMState = CHASING; + if (!((cPlayer *)a_Entity)->IsGameModeCreative()) + { + m_EMState = CHASING; + } } @@ -73,25 +65,32 @@ void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); - m_SeePlayerInterval += a_Dt; - - if (m_SeePlayerInterval > 1) + if (m_EMState == CHASING) + { + CheckEventLostPlayer(); + } + else { - int rem = m_World->GetTickRandomNumber(3) + 1; // Check most of the time but miss occasionally + CheckEventSeePlayer(); + } +} - m_SeePlayerInterval = 0.0; - if (rem >= 2) - { - if (m_EMState == CHASING) - { - CheckEventLostPlayer(); - } - else - { - CheckEventSeePlayer(); - } - } + + + + +void cAggressiveMonster::Attack(float a_Dt) +{ + super::Attack(a_Dt); + + if ((m_Target != NULL) && (m_AttackInterval > 3.0)) + { + // Setting this higher gives us more wiggle room for attackrate + m_AttackInterval = 0.0; + m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0); } } + + diff --git a/src/Mobs/AggressiveMonster.h b/src/Mobs/AggressiveMonster.h index 5a0d93f3d..9cee4e7a7 100644 --- a/src/Mobs/AggressiveMonster.h +++ b/src/Mobs/AggressiveMonster.h @@ -13,16 +13,15 @@ class cAggressiveMonster : typedef cMonster super; public: + cAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); virtual void Tick (float a_Dt, cChunk & a_Chunk) override; virtual void InStateChasing(float a_Dt) override; virtual void EventSeePlayer(cEntity *) override; + virtual void Attack(float a_Dt) override; - -protected: - float m_ChaseTime; } ; diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 98b6c1d28..91ecf3b52 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -8,13 +8,9 @@ #include "../World.h" #include "../Entities/Player.h" #include "../Entities/ExpOrb.h" -#include "../Defines.h" #include "../MonsterConfig.h" #include "../MersenneTwister.h" -#include "../Vector3f.h" -#include "../Vector3i.h" -#include "../Vector3d.h" #include "../Tracer.h" #include "../Chunk.h" #include "../FastRandom.h" @@ -81,11 +77,9 @@ cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString , m_bMovingToDestination(false) , m_DestinationTime( 0 ) , m_DestroyTimer( 0 ) - , m_Jump(0) , m_MobType(a_MobType) , m_SoundHurt(a_SoundHurt) , m_SoundDeath(a_SoundDeath) - , m_SeePlayerInterval (0) , m_AttackDamage(1.0f) , m_AttackRange(2.0f) , m_AttackInterval(0) @@ -110,11 +104,105 @@ void cMonster::SpawnOn(cClientHandle & a_Client) -void cMonster::MoveToPosition( const Vector3f & a_Position ) +void cMonster::TickPathFinding() { + int PosX = (int)floor(GetPosX()); + int PosY = (int)floor(GetPosY()); + int PosZ = (int)floor(GetPosZ()); + + m_FinalDestination.y = (double)FindFirstNonAirBlockPosition(m_FinalDestination.x, m_FinalDestination.z); + + std::vector m_PotentialCoordinates; + m_TraversedCoordinates.push_back(Vector3i(PosX, PosY, PosZ)); + + static const struct // Define which directions the torch can power + { + int x, z; + } gCrossCoords[] = + { + { 1, 0}, + {-1, 0}, + { 0, 1}, + { 0,-1}, + } ; + + for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) + { + if ((gCrossCoords[i].x + PosX == PosX) && (gCrossCoords[i].z + PosZ == PosZ)) + { + continue; + } + + if (IsCoordinateInTraversedList(Vector3i(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ))) + { + continue; + } + + BLOCKTYPE BlockAtY = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ); + BLOCKTYPE BlockAtYP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 1, gCrossCoords[i].z + PosZ); + BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ); + BLOCKTYPE BlockAtYM = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY - 1, gCrossCoords[i].z + PosZ); + + if (!g_BlockIsSolid[BlockAtY] && !g_BlockIsSolid[BlockAtYP] && !IsBlockLava(BlockAtYM)) + { + m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ)); + } + else if (g_BlockIsSolid[BlockAtY] && !g_BlockIsSolid[BlockAtYP] && !g_BlockIsSolid[BlockAtYPP] && !IsBlockLava(BlockAtYM)) + { + m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ)); + } + } + + if (!m_PotentialCoordinates.empty()) + { + Vector3f ShortestCoords = m_PotentialCoordinates.front(); + for (std::vector::const_iterator itr = m_PotentialCoordinates.begin(); itr != m_PotentialCoordinates.end(); ++itr) + { + Vector3f Distance = m_FinalDestination - ShortestCoords; + Vector3f Distance2 = m_FinalDestination - *itr; + if (Distance.SqrLength() > Distance2.SqrLength()) + { + ShortestCoords = *itr; + } + } + + m_Destination = ShortestCoords; + m_Destination.z += 0.5f; + m_Destination.x += 0.5f; + } + else + { + FinishPathFinding(); + } +} + + + + + +void cMonster::MoveToPosition(const Vector3f & a_Position) +{ + FinishPathFinding(); + + m_FinalDestination = a_Position; m_bMovingToDestination = true; + TickPathFinding(); +} + + + + +bool cMonster::IsCoordinateInTraversedList(Vector3i a_Coords) +{ + for (std::vector::const_iterator itr = m_TraversedCoordinates.begin(); itr != m_TraversedCoordinates.end(); ++itr) + { + if (itr->Equals(a_Coords)) + { + return true; + } + } - m_Destination = a_Position; + return false; } @@ -123,10 +211,24 @@ void cMonster::MoveToPosition( const Vector3f & a_Position ) bool cMonster::ReachedDestination() { - Vector3f Distance = (m_Destination) - GetPosition(); - if( Distance.SqrLength() < 2.f ) + if ((m_Destination - GetPosition()).Length() < 0.5f) + { return true; + } + + return false; +} + + + +bool cMonster::ReachedFinalDestination() +{ + if ((GetPosition() - m_FinalDestination).Length() <= m_AttackRange) + { + return true; + } + return false; } @@ -151,23 +253,19 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) // Burning in daylight HandleDaylightBurning(a_Chunk); - - HandlePhysics(a_Dt,a_Chunk); - BroadcastMovementUpdate(); a_Dt /= 1000; if (m_bMovingToDestination) { - Vector3f Pos( GetPosition() ); - Vector3f Distance = m_Destination - Pos; - if( !ReachedDestination() ) + Vector3f Distance = m_Destination - GetPosition(); + if(!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move { Distance.y = 0; Distance.Normalize(); Distance *= 3; - SetSpeedX( Distance.x ); - SetSpeedZ( Distance.z ); + SetSpeedX(Distance.x); + SetSpeedZ(Distance.z); if (m_EMState == ESCAPING) { //Runs Faster when escaping :D otherwise they just walk away @@ -177,40 +275,32 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) } else { - m_bMovingToDestination = false; + if (ReachedFinalDestination()) // If we have reached the ultimate, final destination, stop pathfinding and attack if appropriate + { + FinishPathFinding(); + } + else + { + TickPathFinding(); // We have reached the next point in our path, calculate another point + } } - if( GetSpeed().SqrLength() > 0.f ) + if(m_bOnGround) { - if( m_bOnGround ) + int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); + + if (IsNextYPosReachable(NextHeight)) { - Vector3f NormSpeed = Vector3f(GetSpeed()).NormalizeCopy(); - Vector3f NextBlock = Vector3f( GetPosition() ) + NormSpeed; - int NextHeight; - if (!m_World->TryGetHeight((int)NextBlock.x, (int)NextBlock.z, NextHeight)) - { - // The chunk at NextBlock is not loaded - return; - } - if( NextHeight > (GetPosY() - 1.0) && (NextHeight - GetPosY()) < 2.5 ) - { - m_bOnGround = false; - SetSpeedY(5.f); // Jump!! - } + m_bOnGround = false; + SetSpeedY(5.f); // Jump!! } } } - Vector3d Distance = m_Destination - GetPosition(); - if (Distance.SqrLength() > 0.1f) - { - double Rotation, Pitch; - Distance.Normalize(); - VectorToEuler( Distance.x, Distance.y, Distance.z, Rotation, Pitch ); - SetHeadYaw (Rotation); - SetYaw( Rotation ); - SetPitch( -Pitch ); - } + if (ReachedFinalDestination()) + Attack(a_Dt); + + SetPitchAndYawFromDestination(); switch (m_EMState) { @@ -219,21 +309,87 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) // If enemy passive we ignore checks for player visibility InStateIdle(a_Dt); break; - } - + } case CHASING: { // If we do not see a player anymore skip chasing action InStateChasing(a_Dt); break; - } - + } case ESCAPING: { InStateEscaping(a_Dt); break; } } // switch (m_EMState) + + BroadcastMovementUpdate(); +} + + + + +void cMonster::SetPitchAndYawFromDestination() +{ + Vector3d FinalDestination = m_FinalDestination; + if (m_Target != NULL) + { + if (m_Target->IsPlayer()) + { + FinalDestination.y = ((cPlayer *)m_Target)->GetStance(); + } + else + { + FinalDestination.y = GetHeight(); + } + } + + Vector3d Distance = FinalDestination - GetPosition(); + if (Distance.SqrLength() > 0.1f) + { + { + double Rotation, Pitch; + Distance.Normalize(); + VectorToEuler(Distance.x, Distance.y, Distance.z, Rotation, Pitch); + SetHeadYaw(Rotation); + SetPitch(-Pitch); + } + + { + Vector3d BodyDistance = m_Destination - GetPosition(); + double Rotation, Pitch; + Distance.Normalize(); + VectorToEuler(BodyDistance.x, BodyDistance.y, BodyDistance.z, Rotation, Pitch); + SetYaw(Rotation); + } + } +} + + + + +int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ) +{ + int PosY = (int)floor(GetPosY()); + + if (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))]) + { + while (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))] && (PosY > 0)) + { + PosY--; + } + + return PosY + 1; + } + else + { + while (g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))] && (PosY < cChunkDef::Height)) + { + PosY++; + } + + return PosY; + } } @@ -244,11 +400,13 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) void cMonster::DoTakeDamage(TakeDamageInfo & a_TDI) { super::DoTakeDamage(a_TDI); - if((m_SoundHurt != "") && (m_Health > 0)) m_World->BroadcastSoundEffect(m_SoundHurt, (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 1.0f, 0.8f); + + if((m_SoundHurt != "") && (m_Health > 0)) + m_World->BroadcastSoundEffect(m_SoundHurt, (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 1.0f, 0.8f); + if (a_TDI.Attacker != NULL) { m_Target = a_TDI.Attacker; - AddReference(m_Target); } } @@ -330,55 +488,12 @@ void cMonster::KilledBy(cEntity * a_Killer) -//----State Logic - -const char *cMonster::GetState() -{ - switch(m_EMState) - { - case IDLE: return "Idle"; - case ATTACKING: return "Attacking"; - case CHASING: return "Chasing"; - default: return "Unknown"; - } -} - - - - - -// for debugging -void cMonster::SetState(const AString & a_State) -{ - if (a_State.compare("Idle") == 0) - { - m_EMState = IDLE; - } - else if (a_State.compare("Attacking") == 0) - { - m_EMState = ATTACKING; - } - else if (a_State.compare("Chasing") == 0) - { - m_EMState = CHASING; - } - else - { - LOGD("cMonster::SetState(): Invalid state"); - ASSERT(!"Invalid state"); - } -} - - - - - //Checks to see if EventSeePlayer should be fired //monster sez: Do I see the player void cMonster::CheckEventSeePlayer(void) { // TODO: Rewrite this to use cWorld's DoWithPlayers() - cPlayer * Closest = FindClosestPlayer(); + cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), m_SightDistance); if (Closest != NULL) { @@ -398,7 +513,10 @@ void cMonster::CheckEventLostPlayer(void) if (m_Target != NULL) { pos = m_Target->GetPosition(); - if ((pos - GetPosition()).Length() > m_SightDistance || LineOfSight.Trace(GetPosition(),(pos - GetPosition()), (int)(pos - GetPosition()).Length())) + if ( + ((pos - GetPosition()).Length() > m_SightDistance) || + LineOfSight.Trace(Vector3d(GetPosX(), GetPosY() + 1, GetPosZ()), (pos - GetPosition()), (int)(pos - GetPosition()).Length()) + ) { EventLosePlayer(); } @@ -418,7 +536,6 @@ void cMonster::CheckEventLostPlayer(void) void cMonster::EventSeePlayer(cEntity * a_SeenPlayer) { m_Target = a_SeenPlayer; - AddReference(m_Target); } @@ -427,7 +544,6 @@ void cMonster::EventSeePlayer(cEntity * a_SeenPlayer) void cMonster::EventLosePlayer(void) { - Dereference(m_Target); m_Target = NULL; m_EMState = IDLE; } @@ -436,27 +552,30 @@ void cMonster::EventLosePlayer(void) -// What to do if in Idle State void cMonster::InStateIdle(float a_Dt) { m_IdleInterval += a_Dt; + if (m_IdleInterval > 1) { - // at this interval the results are predictable + // At this interval the results are predictable int rem = m_World->GetTickRandomNumber(6) + 1; - // LOGD("Moving: int: %3.3f rem: %i",idle_interval,rem); - m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds - Vector3f Dist; - Dist.x = (float)(m_World->GetTickRandomNumber(10) - 5); - Dist.z = (float)(m_World->GetTickRandomNumber(10) - 5); + m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds + + Vector3d Dist; + Dist.x = (double)m_World->GetTickRandomNumber(m_SightDistance * 2) - m_SightDistance; + Dist.z = (double)m_World->GetTickRandomNumber(m_SightDistance * 2) - m_SightDistance; + if ((Dist.SqrLength() > 2) && (rem >= 3)) { - m_Destination.x = (float)(GetPosX() + Dist.x); - m_Destination.z = (float)(GetPosZ() + Dist.z); - int PosY; - if (m_World->TryGetHeight((int)m_Destination.x, (int)m_Destination.z, PosY)) + m_Destination.x = GetPosX() + Dist.x; + m_Destination.z = GetPosZ() + Dist.z; + + int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); + + if (IsNextYPosReachable(NextHeight + 1)) { - m_Destination.y = (float)PosY + 1.2f; + m_Destination.y = (double)NextHeight; MoveToPosition(m_Destination); } } @@ -505,22 +624,6 @@ void cMonster::InStateEscaping(float a_Dt) void cMonster::Attack(float a_Dt) { m_AttackInterval += a_Dt * m_AttackRate; - if ((m_Target != NULL) && (m_AttackInterval > 3.0)) - { - // Setting this higher gives us more wiggle room for attackrate - m_AttackInterval = 0.0; - ((cPawn *)m_Target)->TakeDamage(*this); - } -} - - - - - -// Checks for Players close by and if they are visible return the closest -cPlayer * cMonster::FindClosestPlayer(void) -{ - return m_World->FindClosestPlayer(GetPosition(), m_SightDistance); } @@ -536,42 +639,6 @@ void cMonster::GetMonsterConfig(const AString & a_Name) -void cMonster::SetAttackRate(int ar) -{ - m_AttackRate = (float)ar; -} - - - - - -void cMonster::SetAttackRange(float ar) -{ - m_AttackRange = ar; -} - - - - - -void cMonster::SetAttackDamage(float ad) -{ - m_AttackDamage = ad; -} - - - - - -void cMonster::SetSightDistance(float sd) -{ - m_SightDistance = sd; -} - - - - - AString cMonster::MobTypeToString(cMonster::eType a_MobType) { // Mob types aren't sorted, so we need to search linearly: @@ -635,6 +702,8 @@ cMonster::eType cMonster::StringToMobType(const AString & a_Name) cMonster::eFamily cMonster::FamilyFromType(eType a_Type) { + // Passive-agressive mobs are counted in mob spawning code as passive + switch (a_Type) { case mtBat: return mfAmbient; @@ -699,7 +768,7 @@ cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType) case mtMagmaCube: case mtSlime: { - toReturn = new cSlime (Random.NextInt(2) + 1); + toReturn = new cSlime(Random.NextInt(2) + 1); break; } case mtSkeleton: @@ -803,6 +872,13 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk) int RelX = (int)floor(GetPosX()) - GetChunkX() * cChunkDef::Width; int RelZ = (int)floor(GetPosZ()) - GetChunkZ() * cChunkDef::Width; + + if (!a_Chunk.IsLightValid()) + { + m_World->QueueLightChunk(GetChunkX(), GetChunkZ()); + return; + } + if ( (a_Chunk.GetSkyLight(RelX, RelY, RelZ) == 15) && // In the daylight (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index dafb33574..5f32650cf 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -10,7 +10,6 @@ -class Vector3f; class cClientHandle; class cWorld; @@ -74,8 +73,6 @@ public: enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState; enum MPersonality{PASSIVE,AGGRESSIVE,COWARDLY} m_EMPersonality; - float m_SightDistance; - /** Creates the mob object. * If a_ConfigName is not empty, the configuration is loaded using GetMonsterConfig() * a_MobType is the type of the mob (also used in the protocol ( http://wiki.vg/Entities#Mobs , 2012_12_22)) @@ -100,14 +97,9 @@ public: eType GetMobType(void) const {return m_MobType; } eFamily GetMobFamily(void) const; // tolua_end - - - const char * GetState(); - void SetState(const AString & str); virtual void CheckEventSeePlayer(void); virtual void EventSeePlayer(cEntity * a_Player); - virtual cPlayer * FindClosestPlayer(); // non static is easier. also virtual so other mobs can implement their own searching algo /// Reads the monster configuration for the specified monster name and assigns it to this object. void GetMonsterConfig(const AString & a_Name); @@ -121,11 +113,11 @@ public: virtual void Attack(float a_Dt); - int GetAttackRate(){return (int)m_AttackRate;} - void SetAttackRate(int ar); - void SetAttackRange(float ar); - void SetAttackDamage(float ad); - void SetSightDistance(float sd); + int GetAttackRate() { return (int)m_AttackRate; } + void SetAttackRate(float a_AttackRate) { m_AttackRate = a_AttackRate; } + void SetAttackRange(int a_AttackRange) { m_AttackRange = a_AttackRange; } + void SetAttackDamage(int a_AttackDamage) { m_AttackDamage = a_AttackDamage; } + void SetSightDistance(int a_SightDistance) { m_SightDistance = a_SightDistance; } /// Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; } @@ -159,34 +151,72 @@ public: protected: + /* ======= PATHFINDING ======= */ + + /** A pointer to the entity this mobile is aiming to reach */ cEntity * m_Target; + /** Coordinates of the next position that should be reached */ + Vector3d m_Destination; + /** Coordinates for the ultimate, final destination. */ + Vector3d m_FinalDestination; + /** Returns if the ultimate, final destination has been reached */ + bool ReachedFinalDestination(void); + + /** Stores if mobile is currently moving towards the ultimate, final destination */ + bool m_bMovingToDestination; + /** Finds the first non-air block position (not the highest, as cWorld::GetHeight does) + If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1 + If current Y is solid, goes up to find first nonsolid block, and returns that */ + int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ); + + /** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */ + std::vector m_TraversedCoordinates; + /** Returns if coordinate is in the traversed list */ + bool IsCoordinateInTraversedList(Vector3i a_Coords); + + /** Finds the next place to go + This is based on the ultimate, final destination and the current position, as well as the traversed coordinates, and any environmental hazards */ + void TickPathFinding(void); + /** Finishes a pathfinding task, be it due to failure or something else */ + inline void FinishPathFinding(void) + { + m_TraversedCoordinates.clear(); + m_bMovingToDestination = false; + } + /** Sets the body yaw and head yaw/pitch based on next/ultimate destinations */ + void SetPitchAndYawFromDestination(void); + + /* ===========================*/ + float m_AttackRate; float m_IdleInterval; - Vector3f m_Destination; - bool m_bMovingToDestination; + bool m_bPassiveAggressive; float m_DestinationTime; float m_DestroyTimer; - float m_Jump; eType m_MobType; AString m_SoundHurt; AString m_SoundDeath; - float m_SeePlayerInterval; - float m_AttackDamage; - float m_AttackRange; + int m_AttackDamage; + int m_AttackRange; float m_AttackInterval; + int m_SightDistance; bool m_BurnsInDaylight; void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); void HandleDaylightBurning(cChunk & a_Chunk); + inline bool IsNextYPosReachable(int a_PosY) + { + return (a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1); + } } ; // tolua_export diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp index 91ceb5a53..d774d3170 100644 --- a/src/Mobs/PassiveMonster.cpp +++ b/src/Mobs/PassiveMonster.cpp @@ -2,7 +2,6 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "PassiveMonster.h" -#include "../MersenneTwister.h" #include "../World.h" @@ -36,20 +35,9 @@ void cPassiveMonster::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); - m_SeePlayerInterval += a_Dt; - - if (m_SeePlayerInterval > 1) // Check every second + if (m_EMState == ESCAPING) { - int rem = m_World->GetTickRandomNumber(3) + 1; // Check most of the time but miss occasionally - - m_SeePlayerInterval = 0.0; - if (rem >= 2) - { - if (m_EMState == ESCAPING) - { - CheckEventLostPlayer(); - } - } + CheckEventLostPlayer(); } } diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 3d4e97c80..483f1d193 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -108,7 +108,7 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) m_bMovingToDestination = false; } - cPlayer * a_Closest_Player = FindClosestPlayer(); + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), m_SightDistance); if (a_Closest_Player != NULL) { switch (a_Closest_Player->GetEquippedItem().m_ItemType) diff --git a/src/MonsterConfig.cpp b/src/MonsterConfig.cpp index 6165606f0..c06bd6b6f 100644 --- a/src/MonsterConfig.cpp +++ b/src/MonsterConfig.cpp @@ -12,9 +12,9 @@ struct cMonsterConfig::sAttributesStruct { AString m_Name; - double m_SightDistance; - double m_AttackDamage; - double m_AttackRange; + int m_SightDistance; + int m_AttackDamage; + int m_AttackRange; double m_AttackRate; int m_MaxHealth; }; @@ -67,9 +67,9 @@ void cMonsterConfig::Initialize() sAttributesStruct Attributes; AString Name = MonstersIniFile.GetKeyName(i); Attributes.m_Name = Name; - Attributes.m_AttackDamage = MonstersIniFile.GetValueF(Name, "AttackDamage", 0); - Attributes.m_AttackRange = MonstersIniFile.GetValueF(Name, "AttackRange", 0); - Attributes.m_SightDistance = MonstersIniFile.GetValueF(Name, "SightDistance", 0); + Attributes.m_AttackDamage = MonstersIniFile.GetValueI(Name, "AttackDamage", 0); + Attributes.m_AttackRange = MonstersIniFile.GetValueI(Name, "AttackRange", 0); + Attributes.m_SightDistance = MonstersIniFile.GetValueI(Name, "SightDistance", 0); Attributes.m_AttackRate = MonstersIniFile.GetValueF(Name, "AttackRate", 0); Attributes.m_MaxHealth = MonstersIniFile.GetValueI(Name, "MaxHealth", 1); m_pState->AttributesList.push_front(Attributes); @@ -87,10 +87,10 @@ void cMonsterConfig::AssignAttributes(cMonster * a_Monster, const AString & a_Na { if (itr->m_Name.compare(a_Name) == 0) { - a_Monster->SetAttackDamage ((float)itr->m_AttackDamage); - a_Monster->SetAttackRange ((float)itr->m_AttackRange); - a_Monster->SetSightDistance((float)itr->m_SightDistance); - a_Monster->SetAttackRate ((int)itr->m_AttackRate); + a_Monster->SetAttackDamage (itr->m_AttackDamage); + a_Monster->SetAttackRange (itr->m_AttackRange); + a_Monster->SetSightDistance(itr->m_SightDistance); + a_Monster->SetAttackRate ((float)itr->m_AttackRate); a_Monster->SetMaxHealth (itr->m_MaxHealth); return; } -- cgit v1.2.3 From 1f82b6e1920d0f56cad0f7a04c81cb0cf9823a1d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 20:46:22 +0000 Subject: Monsters no longer check for direct line of sight --- src/Mobs/Monster.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 91ecf3b52..bd7894bf9 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -11,7 +11,6 @@ #include "../MonsterConfig.h" #include "../MersenneTwister.h" -#include "../Tracer.h" #include "../Chunk.h" #include "../FastRandom.h" @@ -506,17 +505,10 @@ void cMonster::CheckEventSeePlayer(void) void cMonster::CheckEventLostPlayer(void) -{ - Vector3f pos; - cTracer LineOfSight(GetWorld()); - +{ if (m_Target != NULL) { - pos = m_Target->GetPosition(); - if ( - ((pos - GetPosition()).Length() > m_SightDistance) || - LineOfSight.Trace(Vector3d(GetPosX(), GetPosY() + 1, GetPosZ()), (pos - GetPosition()), (int)(pos - GetPosition()).Length()) - ) + if ((m_Target->GetPosition() - GetPosition()).Length() > m_SightDistance) { EventLosePlayer(); } -- cgit v1.2.3 From 0583b9df391d3b7c8a7ff4f982c4d2e28c42fa36 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 20:46:47 +0000 Subject: Made wolves compatible with new AI code --- src/Mobs/Wolf.cpp | 36 +++++++++++++++++++++++++----------- src/Mobs/Wolf.h | 1 + 2 files changed, 26 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 483f1d193..11e3f690a 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -37,6 +37,26 @@ void cWolf::DoTakeDamage(TakeDamageInfo & a_TDI) +void cWolf::Attack(float a_Dt) +{ + UNUSED(a_Dt); + + if ((m_Target != NULL) && (m_Target->IsPlayer())) + { + if (((cPlayer *)m_Target)->GetName() != m_OwnerName) + { + super::Attack(a_Dt); + } + } + else + { + super::Attack(a_Dt); + } +} + + + + void cWolf::OnRightClicked(cPlayer & a_Player) { @@ -108,7 +128,7 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) m_bMovingToDestination = false; } - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), m_SightDistance); + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); if (a_Closest_Player != NULL) { switch (a_Closest_Player->GetEquippedItem().m_ItemType) @@ -125,9 +145,7 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) SetIsBegging(true); m_World->BroadcastEntityMetadata(*this); } - Vector3f a_NewDestination = a_Closest_Player->GetPosition(); - a_NewDestination.y = a_NewDestination.y + 1; // Look at the head of the player, not his feet. - m_Destination = Vector3f(a_NewDestination); + m_FinalDestination = a_Closest_Player->GetPosition();; m_bMovingToDestination = false; break; } @@ -163,23 +181,19 @@ void cWolf::TickFollowPlayer() return false; } public: - Vector3f OwnerPos; + Vector3d OwnerPos; } Callback; if (m_World->DoWithPlayer(m_OwnerName, Callback)) { // The player is present in the world, follow them: double Distance = (Callback.OwnerPos - GetPosition()).Length(); - if (Distance < 3) - { - m_bMovingToDestination = false; - } - else if ((Distance > 30) && (!IsSitting())) + if ((Distance > 30) && (!IsSitting())) { TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z); } else { - m_Destination = Callback.OwnerPos; + MoveToPosition(Callback.OwnerPos); } } } diff --git a/src/Mobs/Wolf.h b/src/Mobs/Wolf.h index 040e2cf7a..9e5ad03c7 100644 --- a/src/Mobs/Wolf.h +++ b/src/Mobs/Wolf.h @@ -22,6 +22,7 @@ public: virtual void OnRightClicked(cPlayer & a_Player) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; virtual void TickFollowPlayer(); + virtual void Attack(float a_Dt) override; // Get functions bool IsSitting (void) const { return m_IsSitting; } -- cgit v1.2.3 From f0a75f7f73effcaccc6dcb73c42fd8c9f4492dcd Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 24 Jan 2014 19:22:10 +0100 Subject: Fixed a failure in cSquid. Probably due to rounding errors the squid was querying out-of-chunk coords. --- src/Mobs/Squid.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/Squid.cpp b/src/Mobs/Squid.cpp index a311108ae..5a27762ff 100644 --- a/src/Mobs/Squid.cpp +++ b/src/Mobs/Squid.cpp @@ -43,7 +43,8 @@ void cSquid::Tick(float a_Dt, cChunk & a_Chunk) } int RelX = (int)floor(Pos.x) - a_Chunk.GetPosX() * cChunkDef::Width; int RelZ = (int)floor(Pos.z) - a_Chunk.GetPosZ() * cChunkDef::Width; - if (!IsBlockWater(a_Chunk.GetBlock(RelX, RelY, RelZ)) && !IsOnFire()) + BLOCKTYPE BlockType; + if (a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockType) && !IsBlockWater(BlockType) && !IsOnFire()) { // Burn for 10 ticks, then decide again StartBurning(10); -- cgit v1.2.3 From 6c1d992eeba5c300da1a2b7a50fbda52b3774ff4 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 24 Jan 2014 22:23:33 +0100 Subject: Fixed a possible deadlock on client disconnect. --- src/ClientHandle.cpp | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src') diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 18e3d560e..56ad4e4ba 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -148,15 +148,6 @@ cClientHandle::~cClientHandle() SendDisconnect("Server shut down? Kthnxbai"); } - // Queue all remaining outgoing packets to cSocketThreads: - { - cCSLock Lock(m_CSOutgoingData); - AString Data; - m_OutgoingData.ReadAll(Data); - m_OutgoingData.CommitRead(); - cRoot::Get()->GetServer()->WriteToClient(this, Data); - } - // Close the socket as soon as it sends all outgoing data: cRoot::Get()->GetServer()->RemoveClient(this); -- cgit v1.2.3 From bf2af73899ba678e1280aded70703a5d105d295d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 21:54:20 +0000 Subject: Changed a condition to IsGameMode --- src/Mobs/PassiveAggressiveMonster.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/Mobs/PassiveAggressiveMonster.cpp b/src/Mobs/PassiveAggressiveMonster.cpp index 28de65905..4b45f9a2a 100644 --- a/src/Mobs/PassiveAggressiveMonster.cpp +++ b/src/Mobs/PassiveAggressiveMonster.cpp @@ -25,8 +25,7 @@ void cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI) if ((m_Target != NULL) && (m_Target->IsPlayer())) { - cPlayer * Player = (cPlayer *) m_Target; - if (Player->GetGameMode() != 1) + if (!((cPlayer *)m_Target)->IsGameModeCreative()) { m_EMState = CHASING; } -- cgit v1.2.3 From a988063915aa288bf0183509783987941574e2ae Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 21:55:04 +0000 Subject: Miscellaneous improvements --- src/Entities/Pickup.cpp | 14 ++++---------- src/Mobs/Monster.cpp | 9 ++++----- src/Mobs/Monster.h | 22 +++++++++------------- 3 files changed, 17 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp index 001e386a7..55c878b57 100644 --- a/src/Entities/Pickup.cpp +++ b/src/Entities/Pickup.cpp @@ -6,30 +6,24 @@ #endif #include "Pickup.h" +#include "Player.h" #include "../ClientHandle.h" -#include "../Inventory.h" #include "../World.h" -#include "../Simulator/FluidSimulator.h" #include "../Server.h" -#include "Player.h" #include "../Bindings/PluginManager.h" -#include "../Item.h" #include "../Root.h" #include "../Chunk.h" -#include "../Vector3d.h" -#include "../Vector3f.h" - cPickup::cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, bool IsPlayerCreated, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */) : cEntity(etPickup, a_PosX, a_PosY, a_PosZ, 0.2, 0.2) - , m_Timer( 0.f ) + , m_Timer(0.f) , m_Item(a_Item) - , m_bCollected( false ) - , m_bIsPlayerCreated( IsPlayerCreated ) + , m_bCollected(false) + , m_bIsPlayerCreated(IsPlayerCreated) { SetGravity(-10.5f); SetMaxHealth(5); diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index bd7894bf9..3b453552b 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -74,13 +74,12 @@ cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString , m_AttackRate(3) , m_IdleInterval(0) , m_bMovingToDestination(false) - , m_DestinationTime( 0 ) - , m_DestroyTimer( 0 ) + , m_DestroyTimer(0) , m_MobType(a_MobType) , m_SoundHurt(a_SoundHurt) , m_SoundDeath(a_SoundDeath) - , m_AttackDamage(1.0f) - , m_AttackRange(2.0f) + , m_AttackDamage(1) + , m_AttackRange(2) , m_AttackInterval(0) , m_BurnsInDaylight(false) { @@ -492,7 +491,7 @@ void cMonster::KilledBy(cEntity * a_Killer) void cMonster::CheckEventSeePlayer(void) { // TODO: Rewrite this to use cWorld's DoWithPlayers() - cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), m_SightDistance); + cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); if (Closest != NULL) { diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index 5f32650cf..c8129e63d 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -168,6 +168,11 @@ protected: If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1 If current Y is solid, goes up to find first nonsolid block, and returns that */ int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ); + /** Returns if a monster can actually reach a given height by jumping */ + inline bool IsNextYPosReachable(int a_PosY) + { + return (a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1); + } /** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */ std::vector m_TraversedCoordinates; @@ -188,14 +193,9 @@ protected: /* ===========================*/ - float m_AttackRate; - float m_IdleInterval; - - bool m_bPassiveAggressive; - - float m_DestinationTime; + float m_IdleInterval; float m_DestroyTimer; eType m_MobType; @@ -203,20 +203,16 @@ protected: AString m_SoundHurt; AString m_SoundDeath; + float m_AttackRate; int m_AttackDamage; int m_AttackRange; float m_AttackInterval; int m_SightDistance; + void HandleDaylightBurning(cChunk & a_Chunk); bool m_BurnsInDaylight; - void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); - - void HandleDaylightBurning(cChunk & a_Chunk); - inline bool IsNextYPosReachable(int a_PosY) - { - return (a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1); - } + void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); } ; // tolua_export -- cgit v1.2.3 From d0da5d392f64c63fefde352a2a0b569317ca59cc Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 24 Jan 2014 23:03:48 +0100 Subject: Added per-connection comm logging in debug mode. It is meant for debugging only, so it is compiled only into debug mode. It is activated by starting the server with "/logcomm" parameter. --- src/Protocol/Protocol17x.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/Protocol/Protocol17x.h | 5 ++++ src/main.cpp | 25 ++++++++++++++++- 3 files changed, 93 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 9506332dc..d2d0df7f7 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -53,6 +53,18 @@ Implements the 1.7.x protocol classes: +#ifdef _DEBUG +// fwd: main.cpp: +extern bool g_ShouldLogComm; +#endif + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cProtocol172: + cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) : super(a_Client), m_ServerAddress(a_ServerAddress), @@ -63,6 +75,15 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd m_OutPacketLenBuffer(20), // 20 bytes is more than enough for one VarInt m_IsEncrypted(false) { + // Create the comm log file, if so requested: + #ifdef _DEBUG + if (g_ShouldLogComm) + { + cFile::CreateFolder("CommLogs"); + AString FileName = Printf("CommLogs/%x__%s.log", (unsigned)time(NULL), a_Client->GetIPString().c_str()); + m_CommLogFile.Open(FileName, cFile::fmWrite); + } + #endif // _DEBUG } @@ -1065,6 +1086,18 @@ void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) { + // Write the incoming data into the comm log file: + #ifdef _DEBUG + if (g_ShouldLogComm) + { + AString Hex; + CreateHexDump(Hex, a_Data, a_Size, 16); + m_CommLogFile.Printf("Incoming data: %d bytes. %d bytes unparsed already present in buffer.\n%s\n", + a_Size, m_ReceivedData.GetReadableSpace(), Hex.c_str() + ); + } + #endif + if (!m_ReceivedData.Write(a_Data, a_Size)) { // Too much data in the incoming queue, report to caller: @@ -1100,6 +1133,24 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) return; } + // Log the packet info into the comm log file: + #ifdef _DEBUG + if (g_ShouldLogComm) + { + AString PacketData; + bb.ReadAll(PacketData); + bb.ResetRead(); + bb.ReadVarInt(PacketType); + ASSERT(PacketData.size() > 0); + PacketData.resize(PacketData.size() - 1); + AString PacketDataHex; + CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16); + m_CommLogFile.Printf("Next incoming packet is type %u (0x%x), length %u (0x%x) at state %d. Payload:\n%s\n", + PacketType, PacketType, PacketLen, PacketLen, m_State, PacketDataHex.c_str() + ); + } + #endif // _DEBUG + if (!HandlePacket(bb, PacketType)) { // Unknown packet, already been reported, but without the length. Log the length here: @@ -1807,6 +1858,19 @@ cProtocol172::cPacketizer::~cPacketizer() m_Out.ReadAll(DataToSend); m_Protocol.SendData(DataToSend.data(), DataToSend.size()); m_Out.CommitRead(); + + // Log the comm into logfile: + #ifdef _DEBUG + if (g_ShouldLogComm) + { + AString Hex; + ASSERT(DataToSend.size() > 0); + CreateHexDump(Hex, DataToSend.data() + 1, DataToSend.size() - 1, 16); + m_Protocol.m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload:\n%s\n", + DataToSend[0], DataToSend[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str() + ); + } + #endif // _DEBUG } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 3f440f313..b04a1f019 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -223,6 +223,11 @@ protected: CryptoPP::CFB_Mode::Decryption m_Decryptor; CryptoPP::CFB_Mode::Encryption m_Encryptor; + #ifdef _DEBUG + /** The logfile where the comm is logged, when g_ShouldLogComm is true */ + cFile m_CommLogFile; + #endif + /// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets void AddReceivedData(const char * a_Data, int a_Size); diff --git a/src/main.cpp b/src/main.cpp index 340149e0b..68bf6683f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,6 +19,15 @@ bool g_SERVER_TERMINATED = false; // Set to true when the server terminates, so +#ifdef _DEBUG +/** If set to true, the protocols will log each player's communication to a separate logfile */ +bool g_ShouldLogComm; +#endif + + + + + /// If defined, a thorough leak finder will be used (debug MSVC only); leaks will be output to the Output window #define ENABLE_LEAK_FINDER @@ -216,12 +225,26 @@ int main( int argc, char **argv ) #ifndef _DEBUG std::signal(SIGSEGV, NonCtrlHandler); std::signal(SIGTERM, NonCtrlHandler); - std::signal(SIGINT, NonCtrlHandler); + std::signal(SIGINT, NonCtrlHandler); #endif // DEBUG: test the dumpfile creation: // *((int *)0) = 0; + // Check if comm logging is to be enabled: + #ifdef _DEBUG + for (int i = 0; i < argc; i++) + { + if ( + (_stricmp(argv[i], "/commlog") == 0) || + (_stricmp(argv[i], "/logcomm") == 0) + ) + { + g_ShouldLogComm = true; + } + } + #endif // _DEBUG + #if !defined(ANDROID_NDK) try #endif -- cgit v1.2.3 From ebcaaad63aaf854e01f63104a820dfcbd76cc80e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 24 Jan 2014 23:05:26 +0100 Subject: Fixed *nix compilation for previous commit. --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 68bf6683f..902e9e43b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -236,8 +236,8 @@ int main( int argc, char **argv ) for (int i = 0; i < argc; i++) { if ( - (_stricmp(argv[i], "/commlog") == 0) || - (_stricmp(argv[i], "/logcomm") == 0) + (NoCaseCompare(argv[i], "/commlog") == 0) || + (NoCaseCompare(argv[i], "/logcomm") == 0) ) { g_ShouldLogComm = true; -- cgit v1.2.3 From b367a74d3e56927e3a1f55738fb13abd6d667814 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 23:56:05 +0000 Subject: Zombies and skeletons use AI --- src/Mobs/Skeleton.cpp | 11 +++++++---- src/Mobs/Zombie.cpp | 13 ++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp index 509c2191e..4c8e78988 100644 --- a/src/Mobs/Skeleton.cpp +++ b/src/Mobs/Skeleton.cpp @@ -30,15 +30,18 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cSkeleton::MoveToPosition(const Vector3f & a_Position) { - m_Destination = a_Position; - // If the destination is in the sun and if it is not night AND the skeleton isn't on fire then block the movement. - if (!IsOnFire() && m_World->GetTimeOfDay() < 13187 && m_World->GetBlockSkyLight((int) a_Position.x, (int) a_Position.y, (int) a_Position.z) == 15) + if ( + !IsOnFire() && + (m_World->GetTimeOfDay() < 13187) && + (m_World->GetBlockSkyLight((int) a_Position.x, (int) a_Position.y, (int) a_Position.z) == 15) + ) { m_bMovingToDestination = false; return; } - m_bMovingToDestination = true; + + super::MoveToPosition(a_Position); } diff --git a/src/Mobs/Zombie.cpp b/src/Mobs/Zombie.cpp index a046fcc92..27e8ed5fb 100644 --- a/src/Mobs/Zombie.cpp +++ b/src/Mobs/Zombie.cpp @@ -34,15 +34,18 @@ void cZombie::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cZombie::MoveToPosition(const Vector3f & a_Position) { - m_Destination = a_Position; - - // If the destination is in the sun and if it is not night AND the skeleton isn't on fire then block the movement. - if ((m_World->GetBlockSkyLight((int) a_Position.x, (int) a_Position.y, (int) a_Position.z) == 15) && (m_World->GetTimeOfDay() < 13187) && !IsOnFire()) + // If the destination is in the sun and if it is not night AND the zombie isn't on fire then block the movement. + if ( + !IsOnFire() && + (m_World->GetTimeOfDay() < 13187) && + (m_World->GetBlockSkyLight((int)a_Position.x, (int)a_Position.y, (int)a_Position.z) == 15) + ) { m_bMovingToDestination = false; return; } - m_bMovingToDestination = true; + + super::MoveToPosition(a_Position); } -- cgit v1.2.3 From 1112f5adc6f66195ae030673e7831e46ae06c7b0 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 23:56:19 +0000 Subject: Fixed a generator bug --- src/Generating/ChunkGenerator.cpp | 7 ++++++- src/Mobs/Monster.cpp | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index baa5b76b8..27210f49d 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -201,7 +201,7 @@ void cChunkGenerator::Execute(void) while (!m_ShouldTerminate) { cCSLock Lock(m_CS); - while (m_Queue.size() == 0) + while (m_Queue.empty()) { if ((NumChunksGenerated > 16) && (clock() - LastReportTick > CLOCKS_PER_SEC)) { @@ -221,6 +221,11 @@ void cChunkGenerator::Execute(void) LastReportTick = clock(); } + if (m_Queue.empty()) + { + continue; + } + cChunkCoords coords = m_Queue.front(); // Get next coord from queue m_Queue.erase( m_Queue.begin() ); // Remove coordinate from queue bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT); diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 3b453552b..1db16ab71 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -249,6 +249,9 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) return; } + if ((m_Target != NULL) && m_Target->IsDestroyed()) + m_Target = NULL; + // Burning in daylight HandleDaylightBurning(a_Chunk); -- cgit v1.2.3 From fd7fc7e59efebd6b28012c8e8433f53ac853c555 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 24 Jan 2014 23:58:51 +0000 Subject: All mobs now drown (fixes #54) * Implemented mob drowning * Iron Golems and squids are excluded --- src/Entities/Entity.cpp | 95 ++++++++++++++++++++++++++++++++++++++- src/Entities/Entity.h | 23 +++++++++- src/Entities/Player.cpp | 117 ++++++------------------------------------------ src/Entities/Player.h | 22 --------- src/Mobs/IronGolem.h | 4 ++ src/Mobs/Squid.h | 3 ++ 6 files changed, 137 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index ae98a1e91..e22f689d9 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -57,6 +57,8 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d , m_Mass (0.001) // Default 1g , m_Width(a_Width) , m_Height(a_Height) + , m_IsSubmerged(false) + , m_IsSwimming(false) { cCSLock Lock(m_CSCount); m_EntityCount++; @@ -529,7 +531,17 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) { TickInVoid(a_Chunk); } - else { m_TicksSinceLastVoidDamage = 0; } + else + m_TicksSinceLastVoidDamage = 0; + + if (IsMob() || IsPlayer()) + { + // Set swimming state + SetSwimState(a_Chunk); + + // Handle drowning + HandleAir(); + } } @@ -907,6 +919,87 @@ void cEntity::TickInVoid(cChunk & a_Chunk) +void cEntity::SetSwimState(cChunk & a_Chunk) +{ + int RelY = (int)floor(m_LastPosY + 0.1); + if ((RelY < 0) || (RelY >= cChunkDef::Height - 1)) + { + m_IsSwimming = false; + m_IsSubmerged = false; + return; + } + + BLOCKTYPE BlockIn; + int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width; + + // Check if the player is swimming: + // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk + 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: + VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY + 1, RelZ, BlockIn)); + m_IsSubmerged = IsBlockWater(BlockIn); +} + + + + + +void cEntity::HandleAir(void) +{ + // Ref.: http://www.minecraftwiki.net/wiki/Chunk_format + // See if the entity is /submerged/ water (block above is water) + // Get the type of block the entity is standing in: + + if (IsSubmerged()) + { + SetSpeedY(1); // Float in the water + + // Either reduce air level or damage player + if (m_AirLevel < 1) + { + if (m_AirTickTimer < 1) + { + // Damage player + TakeDamage(dtDrowning, NULL, 1, 1, 0); + // Reset timer + m_AirTickTimer = DROWNING_TICKS; + } + else + { + m_AirTickTimer -= 1; + } + } + else + { + // Reduce air supply + m_AirLevel -= 1; + } + } + else + { + // Set the air back to maximum + m_AirLevel = MAX_AIR_LEVEL; + m_AirTickTimer = DROWNING_TICKS; + } +} + + + + + /// Called when the entity starts burning void cEntity::OnStartedBurning(void) { diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 62dc42c3f..f6fa58bb2 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -110,6 +110,8 @@ public: BURN_TICKS_PER_DAMAGE = 20, ///< How many ticks to wait between damaging an entity when it is burning BURN_DAMAGE = 1, ///< How much damage to deal when the entity is burning BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire + MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have + DROWNING_TICKS = 20, ///< Number of ticks per heart of damage } ; cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); @@ -344,7 +346,14 @@ public: 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; } + virtual bool IsInvisible(void) const { return false; } + + /** Returns whether the player is swimming or not */ + virtual bool IsSwimming(void) const{ return m_IsSwimming; } + /** Return whether the player is under water or not */ + virtual bool IsSubmerged(void) const{ return m_IsSubmerged; } + /** Gets remaining air of a monster */ + int GetAirLevel(void) const { return m_AirLevel; } // tolua_end @@ -412,6 +421,18 @@ protected: virtual void Destroyed(void) {} // Called after the entity has been destroyed void SetWorld(cWorld * a_World) { m_World = a_World; } + + /** Called in each tick to handle air-related processing i.e. drowning */ + virtual void HandleAir(); + /** Called once per tick to set IsSwimming and IsSubmerged */ + virtual void SetSwimState(cChunk & a_Chunk); + + /** If an entity is currently swimming in or submerged under water */ + bool m_IsSwimming, m_IsSubmerged; + + /** Air level of a mobile */ + int m_AirLevel; + int m_AirTickTimer; private: // Measured in degrees, [-180, +180) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 377194efc..2a5baedb6 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -7,7 +7,6 @@ #include "../UI/Window.h" #include "../UI/WindowOwner.h" #include "../World.h" -#include "Pickup.h" #include "../Bindings/PluginManager.h" #include "../BlockEntities/BlockEntity.h" #include "../GroupManager.h" @@ -36,8 +35,6 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) : super(etPlayer, 0.6, 1.8) - , m_AirLevel( MAX_AIR_LEVEL ) - , m_AirTickTimer(DROWNING_TICKS) , m_bVisible(true) , m_FoodLevel(MAX_FOOD_LEVEL) , m_FoodSaturationLevel(5) @@ -108,9 +105,23 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ() ); } + m_LastJumpHeight = (float)(GetPosY()); m_LastGroundHeight = (float)(GetPosY()); m_Stance = GetPosY() + 1.62; + + if (m_GameMode == gmNotSet) + { + cWorld * World = cRoot::Get()->GetWorld(GetLoadedWorldName()); + if (World == NULL) + { + World = cRoot::Get()->GetDefaultWorld(); + } + if (World->IsGameModeCreative()) + { + m_CanFly = true; + } + } cRoot::Get()->GetServer()->PlayerCreated(this); } @@ -197,12 +208,6 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) super::Tick(a_Dt, a_Chunk); - // Set player swimming state - SetSwimState(a_Chunk); - - // Handle air drowning stuff - HandleAir(); - // Handle charging the bow: if (m_IsChargingBow) { @@ -1630,27 +1635,12 @@ bool cPlayer::LoadFromDisk() m_CurrentXp = (short) root.get("xpCurrent", 0).asInt(); m_IsFlying = root.get("isflying", 0).asBool(); - //SetExperience(root.get("experience", 0).asInt()); - m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt(); if (m_GameMode == eGameMode_Creative) { m_CanFly = true; } - else if (m_GameMode == eGameMode_NotSet) - { - cWorld * World = cRoot::Get()->GetWorld(GetLoadedWorldName()); - if (World == NULL) - { - World = cRoot::Get()->GetDefaultWorld(); - } - - if (World->GetGameMode() == eGameMode_Creative) - { - m_CanFly = true; - } - } m_Inventory.LoadFromJson(root["inventory"]); @@ -1767,85 +1757,6 @@ void cPlayer::UseEquippedItem(void) -void cPlayer::SetSwimState(cChunk & a_Chunk) -{ - int RelY = (int)floor(m_LastPosY + 0.1); - if ((RelY < 0) || (RelY >= cChunkDef::Height - 1)) - { - m_IsSwimming = false; - m_IsSubmerged = false; - return; - } - - BLOCKTYPE BlockIn; - int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width; - int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width; - - // Check if the player is swimming: - // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk - 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: - VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY + 1, RelZ, BlockIn)); - m_IsSubmerged = IsBlockWater(BlockIn); -} - - - - - -void cPlayer::HandleAir(void) -{ - // Ref.: http://www.minecraftwiki.net/wiki/Chunk_format - // see if the player is /submerged/ water (block above is water) - // Get the type of block the player's standing in: - - if (IsSubmerged()) - { - // either reduce air level or damage player - if (m_AirLevel < 1) - { - if (m_AirTickTimer < 1) - { - // damage player - TakeDamage(dtDrowning, NULL, 1, 1, 0); - // reset timer - m_AirTickTimer = DROWNING_TICKS; - } - else - { - m_AirTickTimer -= 1; - } - } - else - { - // reduce air supply - m_AirLevel -= 1; - } - } - else - { - // set the air back to maximum - m_AirLevel = MAX_AIR_LEVEL; - m_AirTickTimer = DROWNING_TICKS; - } -} - - - - - void cPlayer::HandleFood(void) { // Ref.: http://www.minecraftwiki.net/wiki/Hunger diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 46d0de69d..449df978f 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -31,8 +31,6 @@ public: MAX_HEALTH = 20, MAX_FOOD_LEVEL = 20, EATING_TICKS = 30, ///< Number of ticks it takes to eat an item - MAX_AIR_LEVEL = 300, - DROWNING_TICKS = 10, //number of ticks per heart of damage } ; // tolua_end @@ -241,8 +239,6 @@ public: int GetFoodTickTimer (void) const { return m_FoodTickTimer; } double GetFoodExhaustionLevel (void) const { return m_FoodExhaustionLevel; } int GetFoodPoisonedTicksRemaining(void) const { return m_FoodPoisonedTicksRemaining; } - - int GetAirLevel (void) const { return m_AirLevel; } /// Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore bool IsSatiated(void) const { return (m_FoodLevel >= MAX_FOOD_LEVEL); } @@ -353,12 +349,6 @@ public: /// If true the player can fly even when he's not in creative. void SetCanFly(bool a_CanFly); - /// Returns whether the player is swimming or not - virtual bool IsSwimming(void) const{ return m_IsSwimming; } - - /// Return whether the player is under water or not - virtual bool IsSubmerged(void) const{ return m_IsSubmerged; } - /// Returns wheter the player can fly or not. virtual bool CanFly(void) const { return m_CanFly; } // tolua_end @@ -389,12 +379,6 @@ protected: XP_TO_LEVEL30 = 825 } ; - /// Player's air level (for swimming) - int m_AirLevel; - - /// used to time ticks between damage taken via drowning/suffocation - int m_AirTickTimer; - bool m_bVisible; // Food-related variables: @@ -490,12 +474,6 @@ protected: /// Called in each tick if the player is fishing to make sure the floater dissapears when the player doesn't have a fishing rod as equipped item. void HandleFloater(void); - - /// Called in each tick to handle air-related processing i.e. drowning - void HandleAir(); - - /// Called once per tick to set IsSwimming and IsSubmerged - void SetSwimState(cChunk & a_Chunk); /// Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) void ApplyFoodExhaustionFromMovement(); diff --git a/src/Mobs/IronGolem.h b/src/Mobs/IronGolem.h index d49ff4cab..41c60438c 100644 --- a/src/Mobs/IronGolem.h +++ b/src/Mobs/IronGolem.h @@ -18,6 +18,10 @@ public: CLASS_PROTODEF(cIronGolem); virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + + // Iron golems do not drown + virtual void HandleAir(void) override {} + virtual void SetSwimState(cChunk & a_Chunk) override {} } ; diff --git a/src/Mobs/Squid.h b/src/Mobs/Squid.h index ad299b95c..a9dba8b70 100644 --- a/src/Mobs/Squid.h +++ b/src/Mobs/Squid.h @@ -21,6 +21,9 @@ public: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + // Squids do not drown (or float) + virtual void HandleAir(void) override {} + virtual void SetSwimState(cChunk & a_Chunk) override {} } ; -- cgit v1.2.3 From b2fd91ee6b391b36a8b2d88d818fe370798238e8 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sat, 25 Jan 2014 05:25:43 -0800 Subject: Reformatted Bindings Dependecies --- src/CMakeLists.txt | 86 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 51182d3bc..4058c1873 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,34 +16,64 @@ if (NOT MSVC) #lib dependecies are not included - set(BINDING_DEPENDECIES ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ChunkDef.h BiomeDef.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} OSSupport/File.h Bindings/LuaFunctions.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginManager.h Bindings/Plugin.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginLua.h Bindings/WebPlugin.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/LuaWindow.h BlockID.h StringUtils.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Defines.h ChatColor.h ClientHandle.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Entity.h Entities/Floater.h ) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Pawn.h Entities/Player.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Pickup.h Entities/ProjectileEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/TNTEntity.h Entities/Effects.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Server.h World.h Inventory.h Enchantments.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Item.h ItemGrid.h BlockEntities/BlockEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/BlockEntityWithItems.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/ChestEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DropSpenserEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DispenserEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DropperEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/FurnaceEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/HopperEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/JukeboxEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/NoteEntity.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/SignEntity.h WebAdmin.h Root.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Vector3f.h Vector3d.h Vector3i.h Matrix4f.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Cuboid.h BoundingBox.h Tracer.h Group.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockArea.h Generating/ChunkDesc.h) - set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} CraftingRecipes.h UI/Window.h Mobs/Monster.h) + set(BINDING_DEPENDECIES + ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua + ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg + ChunkDef.h + BiomeDef.h + OSSupport/File.h + Bindings/LuaFunctions.h + Bindings/PluginManager.h + Bindings/Plugin.h + Bindings/PluginLua.h + Bindings/WebPlugin.h + Bindings/LuaWindow.h + BlockID.h + StringUtils.h + Defines.h + ChatColor.h + ClientHandle.h + Entities/Entity.h + Entities/Floater.h + Entities/Pawn.h + Entities/Player.h + Entities/Pickup.h + Entities/ProjectileEntity.h + Entities/TNTEntity.h + Entities/Effects.h + Server.h + World.h + Inventory.h + Enchantments.h + Item.h + ItemGrid.h + BlockEntities/BlockEntity.h + BlockEntities/BlockEntityWithItems.h + BlockEntities/ChestEntity.h + BlockEntities/DropSpenserEntity.h + BlockEntities/DispenserEntity.h + BlockEntities/DropperEntity.h + BlockEntities/FurnaceEntity.h + BlockEntities/HopperEntity.h + BlockEntities/JukeboxEntity.h + BlockEntities/NoteEntity.h + BlockEntities/SignEntity.h + WebAdmin.h + Root.h + Vector3f.h + Vector3d.h + Vector3i.h + Matrix4f.h + Cuboid.h + BoundingBox.h + Tracer.h + Group.h + BlockArea.h + Generating/ChunkDesc.h + CraftingRecipes.h + UI/Window.h + Mobs/Monster.h + ) include_directories(Bindings) include_directories(.) -- cgit v1.2.3 From 45bc1ff033271bc0c6a9e5931a00c554e065c375 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sat, 25 Jan 2014 05:35:04 -0800 Subject: Added dependecy output to Bindings/BindingsDependencies.txt --- src/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4058c1873..9d03a4ffa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -94,6 +94,13 @@ if (NOT MSVC) target_link_libraries(Bindings lua sqlite tolualib) + #clear file + file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt) + foreach(dependecy ${BINDING_DEPENDECIES}) + #write each dependecy on a seperate line + file(APPEND ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt "${dependecy}\n") + endforeach() + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "Bindings.cpp Bindings.h") foreach(folder ${FOLDERS}) -- cgit v1.2.3 From 59b8205f02eb7bf2954acba56fd63f485a30ece5 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sat, 25 Jan 2014 05:51:03 -0800 Subject: Extracted cSocket::GetErrorString into GetOSErrorString --- src/OSSupport/BlockingTCPLink.cpp | 4 +-- src/OSSupport/Errors.cpp | 52 +++++++++++++++++++++++++++++++++++++++ src/OSSupport/Errors.h | 3 +++ src/OSSupport/Socket.cpp | 52 --------------------------------------- src/OSSupport/Socket.h | 7 +++--- src/OSSupport/SocketThreads.cpp | 3 ++- 6 files changed, 62 insertions(+), 59 deletions(-) create mode 100644 src/OSSupport/Errors.cpp create mode 100644 src/OSSupport/Errors.h (limited to 'src') diff --git a/src/OSSupport/BlockingTCPLink.cpp b/src/OSSupport/BlockingTCPLink.cpp index 08aec0c65..af50eda5d 100644 --- a/src/OSSupport/BlockingTCPLink.cpp +++ b/src/OSSupport/BlockingTCPLink.cpp @@ -2,7 +2,7 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "BlockingTCPLink.h" - +#include "Errors.h" @@ -75,7 +75,7 @@ bool cBlockingTCPLink::Connect(const char * iAddress, unsigned int iPort) server.sin_port = htons( (unsigned short)iPort); if (connect(m_Socket, (struct sockaddr *)&server, sizeof(server))) { - LOGWARN("cTCPLink: Connection to \"%s:%d\" failed (%s)", iAddress, iPort, cSocket::GetErrorString( cSocket::GetLastError() ).c_str() ); + LOGWARN("cTCPLink: Connection to \"%s:%d\" failed (%s)", iAddress, iPort,GetOSErrorString( cSocket::GetLastError() ).c_str() ); CloseSocket(); return false; } diff --git a/src/OSSupport/Errors.cpp b/src/OSSupport/Errors.cpp new file mode 100644 index 000000000..b2e8880bb --- /dev/null +++ b/src/OSSupport/Errors.cpp @@ -0,0 +1,52 @@ + +#include "Globals.h" + +#include "Errors.h" + +AString GetOSErrorString( int a_ErrNo ) +{ + char buffer[ 1024 ]; + AString Out; + + #ifdef _WIN32 + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, a_ErrNo, 0, buffer, ARRAYCOUNT(buffer), NULL); + Printf(Out, "%d: %s", a_ErrNo, buffer); + if (!Out.empty() && (Out[Out.length() - 1] == '\n')) + { + Out.erase(Out.length() - 2); + } + return Out; + + #else // _WIN32 + + // According to http://linux.die.net/man/3/strerror_r there are two versions of strerror_r(): + + #if ( _GNU_SOURCE ) && !defined(ANDROID_NDK) // GNU version of strerror_r() + + char * res = strerror_r( errno, buffer, ARRAYCOUNT(buffer) ); + if( res != NULL ) + { + Printf(Out, "%d: %s", a_ErrNo, res); + return Out; + } + + #else // XSI version of strerror_r(): + + int res = strerror_r( errno, buffer, ARRAYCOUNT(buffer) ); + if( res == 0 ) + { + Printf(Out, "%d: %s", a_ErrNo, buffer); + return Out; + } + + #endif // strerror_r() version + + else + { + Printf(Out, "Error %d while getting error string for error #%d!", errno, a_ErrNo); + return Out; + } + + #endif // else _WIN32 +} diff --git a/src/OSSupport/Errors.h b/src/OSSupport/Errors.h new file mode 100644 index 000000000..72ba98862 --- /dev/null +++ b/src/OSSupport/Errors.h @@ -0,0 +1,3 @@ + +AString GetOSErrorString(int a_ErrNo); + diff --git a/src/OSSupport/Socket.cpp b/src/OSSupport/Socket.cpp index d80c9bb3d..4226a7535 100644 --- a/src/OSSupport/Socket.cpp +++ b/src/OSSupport/Socket.cpp @@ -105,58 +105,6 @@ void cSocket::ShutdownReadWrite(void) - -AString cSocket::GetErrorString( int a_ErrNo ) -{ - char buffer[ 1024 ]; - AString Out; - - #ifdef _WIN32 - - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, a_ErrNo, 0, buffer, ARRAYCOUNT(buffer), NULL); - Printf(Out, "%d: %s", a_ErrNo, buffer); - if (!Out.empty() && (Out[Out.length() - 1] == '\n')) - { - Out.erase(Out.length() - 2); - } - return Out; - - #else // _WIN32 - - // According to http://linux.die.net/man/3/strerror_r there are two versions of strerror_r(): - - #if ( _GNU_SOURCE ) && !defined(ANDROID_NDK) // GNU version of strerror_r() - - char * res = strerror_r( errno, buffer, ARRAYCOUNT(buffer) ); - if( res != NULL ) - { - Printf(Out, "%d: %s", a_ErrNo, res); - return Out; - } - - #else // XSI version of strerror_r(): - - int res = strerror_r( errno, buffer, ARRAYCOUNT(buffer) ); - if( res == 0 ) - { - Printf(Out, "%d: %s", a_ErrNo, buffer); - return Out; - } - - #endif // strerror_r() version - - else - { - Printf(Out, "Error %d while getting error string for error #%d!", errno, a_ErrNo); - return Out; - } - - #endif // else _WIN32 -} - - - - int cSocket::GetLastError() { #ifdef _WIN32 diff --git a/src/OSSupport/Socket.h b/src/OSSupport/Socket.h index 91c9ca5fd..4ca3d61f4 100644 --- a/src/OSSupport/Socket.h +++ b/src/OSSupport/Socket.h @@ -14,7 +14,7 @@ #endif - +#include "Errors.h" class cSocket @@ -57,11 +57,10 @@ public: /// Initializes the network stack. Returns 0 on success, or another number as an error code. static int WSAStartup(void); - static AString GetErrorString(int a_ErrNo); static int GetLastError(); static AString GetLastErrorString(void) { - return GetErrorString(GetLastError()); + return GetOSErrorString(GetLastError()); } /// Creates a new socket of the specified address family @@ -115,4 +114,4 @@ public: private: xSocket m_Socket; AString m_IPString; -}; \ No newline at end of file +}; diff --git a/src/OSSupport/SocketThreads.cpp b/src/OSSupport/SocketThreads.cpp index b8069cf00..74932daf8 100644 --- a/src/OSSupport/SocketThreads.cpp +++ b/src/OSSupport/SocketThreads.cpp @@ -7,6 +7,7 @@ #include "Globals.h" #include "SocketThreads.h" +#include "Errors.h" @@ -556,7 +557,7 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) if (Sent < 0) { int Err = cSocket::GetLastError(); - LOGWARNING("Error %d while writing to client \"%s\", disconnecting. \"%s\"", Err, m_Slots[i].m_Socket.GetIPString().c_str(), cSocket::GetErrorString(Err).c_str()); + LOGWARNING("Error %d while writing to client \"%s\", disconnecting. \"%s\"", Err, m_Slots[i].m_Socket.GetIPString().c_str(), GetOSErrorString(Err).c_str()); m_Slots[i].m_Socket.CloseSocket(); if (m_Slots[i].m_Client != NULL) { -- cgit v1.2.3 From 977e277094750a22284b4a738269db295af3cad3 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sat, 25 Jan 2014 06:02:20 -0800 Subject: Switched cEvent to GetOSErrorString --- src/OSSupport/Errors.cpp | 1 + src/OSSupport/Errors.h | 2 ++ src/OSSupport/Event.cpp | 29 +++++++++++------------------ 3 files changed, 14 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/OSSupport/Errors.cpp b/src/OSSupport/Errors.cpp index b2e8880bb..2e05f1df1 100644 --- a/src/OSSupport/Errors.cpp +++ b/src/OSSupport/Errors.cpp @@ -50,3 +50,4 @@ AString GetOSErrorString( int a_ErrNo ) #endif // else _WIN32 } + diff --git a/src/OSSupport/Errors.h b/src/OSSupport/Errors.h index 72ba98862..8ce9deb10 100644 --- a/src/OSSupport/Errors.h +++ b/src/OSSupport/Errors.h @@ -1,3 +1,5 @@ +#pragma once + AString GetOSErrorString(int a_ErrNo); diff --git a/src/OSSupport/Event.cpp b/src/OSSupport/Event.cpp index fe1128dc9..649a0a3cf 100644 --- a/src/OSSupport/Event.cpp +++ b/src/OSSupport/Event.cpp @@ -7,9 +7,7 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Event.h" -#if not defined(_WIN32) -#include -#endif +#include "Errors.h" @@ -37,18 +35,16 @@ cEvent::cEvent(void) m_Event = sem_open(EventName.c_str(), O_CREAT, 777, 0 ); if (m_Event == SEM_FAILED) { - char buffer[1024]; - strerror_r(errno,buffer,1024); - LOGERROR("cEvent: Cannot create event, err = %s. Aborting server.", buffer); + AString error = GetOSErrorString(errno); + LOGERROR("cEvent: Cannot create event, err = %s. Aborting server.", error.c_str()); abort(); } // Unlink the semaphore immediately - it will continue to function but will not pollute the namespace // We don't store the name, so can't call this in the destructor if (sem_unlink(EventName.c_str()) != 0) { - char buffer[1024]; - strerror_r(errno,buffer,1024); - LOGWARN("ERROR: Could not unlink cEvent. (%s)", buffer); + AString error = GetOSErrorString(errno); + LOGWARN("ERROR: Could not unlink cEvent. (%s)", error.c_str()); } } #endif // *nix @@ -67,9 +63,8 @@ cEvent::~cEvent() { if (sem_close(m_Event) != 0) { - char buffer[1024]; - strerror_r(errno,buffer,1024); - LOGERROR("ERROR: Could not close cEvent. (%s)", buffer); + AString error = GetOSErrorString(errno); + LOGERROR("ERROR: Could not close cEvent. (%s)", error.c_str()); } } else @@ -96,9 +91,8 @@ void cEvent::Wait(void) int res = sem_wait(m_Event); if (res != 0 ) { - char buffer[1024]; - strerror_r(errno,buffer,1024); - LOGWARN("cEvent: waiting for the event failed: %i, err = %s. Continuing, but server may be unstable.", res, buffer); + AString error = GetOSErrorString(errno); + LOGWARN("cEvent: waiting for the event failed: %i, err = %s. Continuing, but server may be unstable.", res, error.c_str()); } #endif } @@ -118,9 +112,8 @@ void cEvent::Set(void) int res = sem_post(m_Event); if (res != 0) { - char buffer[1024]; - strerror_r(errno,buffer,1024); - LOGWARN("cEvent: Could not set cEvent: %i, err = %s", res, buffer); + AString error = GetOSErrorString(errno); + LOGWARN("cEvent: Could not set cEvent: %i, err = %s", res, error.c_str()); } #endif } -- cgit v1.2.3 From 96b4af15963ac70b25ab243d84d48221a3d41369 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 25 Jan 2014 15:06:21 +0100 Subject: Protocol17: Comm logging shows the data left over from previous parse. --- src/Protocol/Protocol17x.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index d2d0df7f7..8abe4f259 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1090,10 +1090,23 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) #ifdef _DEBUG if (g_ShouldLogComm) { + if (m_ReceivedData.GetReadableSpace() > 0) + { + AString AllData; + int OldReadableSpace = m_ReceivedData.GetReadableSpace(); + m_ReceivedData.ReadAll(AllData); + m_ReceivedData.ResetRead(); + m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace); + AString Hex; + CreateHexDump(Hex, AllData.data(), AllData.size(), 16); + m_CommLogFile.Printf("Incoming data, %d (0x%x) bytes unparsed already present in buffer:\n%s\n", + AllData.size(), AllData.size(), Hex.c_str() + ); + } AString Hex; CreateHexDump(Hex, a_Data, a_Size, 16); - m_CommLogFile.Printf("Incoming data: %d bytes. %d bytes unparsed already present in buffer.\n%s\n", - a_Size, m_ReceivedData.GetReadableSpace(), Hex.c_str() + m_CommLogFile.Printf("Incoming data: %d (0x%x) bytes: \n%s\n", + a_Size, a_Size, Hex.c_str() ); } #endif -- cgit v1.2.3 From 5aa3fc4c564252359613eb0d91225247f65e0d45 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 25 Jan 2014 15:27:34 +0100 Subject: Added cFile::Flush(). This is useful when using cFile as a log file and we know the server may crash after a specific write, so we flush the file before continuing. --- src/OSSupport/File.cpp | 9 +++++++++ src/OSSupport/File.h | 45 +++++++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/OSSupport/File.cpp b/src/OSSupport/File.cpp index 9f7c0d439..0ebd04915 100644 --- a/src/OSSupport/File.cpp +++ b/src/OSSupport/File.cpp @@ -450,3 +450,12 @@ int cFile::Printf(const char * a_Fmt, ...) + +void cFile::Flush(void) +{ + fflush(m_File); +} + + + + diff --git a/src/OSSupport/File.h b/src/OSSupport/File.h index 01663a229..07fce6661 100644 --- a/src/OSSupport/File.h +++ b/src/OSSupport/File.h @@ -18,6 +18,8 @@ Usage: 2, Check if the file was opened using IsOpen() 3, Read / write 4, Destroy the instance + +For reading entire files into memory, just use the static cFile::ReadWholeFile() */ @@ -55,7 +57,7 @@ public: static const char PathSeparator = '/'; #endif - /// The mode in which to open the file + /** The mode in which to open the file */ enum eMode { fmRead, // Read-only. If the file doesn't exist, object will not be valid @@ -63,13 +65,13 @@ public: fmReadWrite // Read/write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning } ; - /// Simple constructor - creates an unopened file object, use Open() to open / create a real file + /** Simple constructor - creates an unopened file object, use Open() to open / create a real file */ cFile(void); - /// Constructs and opens / creates the file specified, use IsOpen() to check for success + /** Constructs and opens / creates the file specified, use IsOpen() to check for success */ cFile(const AString & iFileName, eMode iMode); - /// Auto-closes the file, if open + /** Auto-closes the file, if open */ ~cFile(); bool Open(const AString & iFileName, eMode iMode); @@ -77,60 +79,63 @@ public: bool IsOpen(void) const; bool IsEOF(void) const; - /// Reads up to iNumBytes bytes into iBuffer, returns the number of bytes actually read, or -1 on failure; asserts if not open + /** Reads up to iNumBytes bytes into iBuffer, returns the number of bytes actually read, or -1 on failure; asserts if not open */ int Read (void * iBuffer, int iNumBytes); - /// Writes up to iNumBytes bytes from iBuffer, returns the number of bytes actually written, or -1 on failure; asserts if not open + /** Writes up to iNumBytes bytes from iBuffer, returns the number of bytes actually written, or -1 on failure; asserts if not open */ int Write(const void * iBuffer, int iNumBytes); - /// Seeks to iPosition bytes from file start, returns old position or -1 for failure; asserts if not open + /** Seeks to iPosition bytes from file start, returns old position or -1 for failure; asserts if not open */ int Seek (int iPosition); - /// Returns the current position (bytes from file start) or -1 for failure; asserts if not open + /** Returns the current position (bytes from file start) or -1 for failure; asserts if not open */ int Tell (void) const; - /// Returns the size of file, in bytes, or -1 for failure; asserts if not open + /** Returns the size of file, in bytes, or -1 for failure; asserts if not open */ int GetSize(void) const; - /// Reads the file from current position till EOF into an AString; returns the number of bytes read or -1 for error + /** Reads the file from current position till EOF into an AString; returns the number of bytes read or -1 for error */ int ReadRestOfFile(AString & a_Contents); // tolua_begin - /// Returns true if the file specified exists + /** Returns true if the file specified exists */ static bool Exists(const AString & a_FileName); - /// Deletes a file, returns true if successful + /** Deletes a file, returns true if successful */ static bool Delete(const AString & a_FileName); - /// Renames a file or folder, returns true if successful. May fail if dest already exists (libc-dependant)! + /** Renames a file or folder, returns true if successful. May fail if dest already exists (libc-dependant)! */ static bool Rename(const AString & a_OrigPath, const AString & a_NewPath); - /// Copies a file, returns true if successful. + /** Copies a file, returns true if successful. */ static bool Copy(const AString & a_SrcFileName, const AString & a_DstFileName); - /// Returns true if the specified path is a folder + /** Returns true if the specified path is a folder */ static bool IsFolder(const AString & a_Path); - /// Returns true if the specified path is a regular file + /** Returns true if the specified path is a regular file */ static bool IsFile(const AString & a_Path); - /// Returns the size of the file, or a negative number on error + /** Returns the size of the file, or a negative number on error */ static int GetSize(const AString & a_FileName); - /// Creates a new folder with the specified name. Returns true if successful. Path may be relative or absolute + /** Creates a new folder with the specified name. Returns true if successful. Path may be relative or absolute */ static bool CreateFolder(const AString & a_FolderPath); - /// Returns the entire contents of the specified file as a string. Returns empty string on error. + /** Returns the entire contents of the specified file as a string. Returns empty string on error. */ static AString ReadWholeFile(const AString & a_FileName); // tolua_end - /// Returns the list of all items in the specified folder (files, folders, nix pipes, whatever's there). + /** Returns the list of all items in the specified folder (files, folders, nix pipes, whatever's there). */ static AStringVector GetFolderContents(const AString & a_Folder); // Exported in ManualBindings.cpp int Printf(const char * a_Fmt, ...); + /** Flushes all the bufferef output into the file (only when writing) */ + void Flush(void); + private: #ifdef USE_STDIO_FILE FILE * m_File; -- cgit v1.2.3 From ff066453b805748d6e665b3ad219a62c777e4453 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 25 Jan 2014 15:28:16 +0100 Subject: Comm logging is available in both Debug and Release modes. --- src/Protocol/Protocol17x.cpp | 26 ++++++++++++++++---------- src/Protocol/Protocol17x.h | 2 -- src/main.cpp | 4 ---- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 8abe4f259..504dd99c3 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -53,10 +53,8 @@ Implements the 1.7.x protocol classes: -#ifdef _DEBUG // fwd: main.cpp: extern bool g_ShouldLogComm; -#endif @@ -76,14 +74,12 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd m_IsEncrypted(false) { // Create the comm log file, if so requested: - #ifdef _DEBUG if (g_ShouldLogComm) { cFile::CreateFolder("CommLogs"); AString FileName = Printf("CommLogs/%x__%s.log", (unsigned)time(NULL), a_Client->GetIPString().c_str()); m_CommLogFile.Open(FileName, cFile::fmWrite); } - #endif // _DEBUG } @@ -1087,7 +1083,6 @@ void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) { // Write the incoming data into the comm log file: - #ifdef _DEBUG if (g_ShouldLogComm) { if (m_ReceivedData.GetReadableSpace() > 0) @@ -1109,7 +1104,6 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) a_Size, a_Size, Hex.c_str() ); } - #endif if (!m_ReceivedData.Write(a_Data, a_Size)) { @@ -1147,7 +1141,6 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) } // Log the packet info into the comm log file: - #ifdef _DEBUG if (g_ShouldLogComm) { AString PacketData; @@ -1162,7 +1155,6 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) PacketType, PacketType, PacketLen, PacketLen, m_State, PacketDataHex.c_str() ); } - #endif // _DEBUG if (!HandlePacket(bb, PacketType)) { @@ -1180,6 +1172,12 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) LOGD("Packet contents:\n%s", Out.c_str()); #endif // _DEBUG + // Put a message in the comm log: + if (g_ShouldLogComm) + { + m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n"); + } + return; } @@ -1189,6 +1187,16 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x, state %d. Read %u bytes, packet contained %u bytes", PacketType, m_State, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen ); + + // Put a message in the comm log: + if (g_ShouldLogComm) + { + m_CommLogFile.Printf("^^^^^^ Wrong number of bytes read for this packet (exp %d left, got %d left) ^^^^^^\n\n\n", + 1, bb.GetReadableSpace() + ); + m_CommLogFile.Flush(); + } + ASSERT(!"Read wrong number of bytes!"); m_Client->PacketError(PacketType); } @@ -1873,7 +1881,6 @@ cProtocol172::cPacketizer::~cPacketizer() m_Out.CommitRead(); // Log the comm into logfile: - #ifdef _DEBUG if (g_ShouldLogComm) { AString Hex; @@ -1883,7 +1890,6 @@ cProtocol172::cPacketizer::~cPacketizer() DataToSend[0], DataToSend[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str() ); } - #endif // _DEBUG } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index b04a1f019..cac7f0d29 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -223,10 +223,8 @@ protected: CryptoPP::CFB_Mode::Decryption m_Decryptor; CryptoPP::CFB_Mode::Encryption m_Encryptor; - #ifdef _DEBUG /** The logfile where the comm is logged, when g_ShouldLogComm is true */ cFile m_CommLogFile; - #endif /// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets diff --git a/src/main.cpp b/src/main.cpp index 902e9e43b..06b344c25 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,10 +19,8 @@ bool g_SERVER_TERMINATED = false; // Set to true when the server terminates, so -#ifdef _DEBUG /** If set to true, the protocols will log each player's communication to a separate logfile */ bool g_ShouldLogComm; -#endif @@ -232,7 +230,6 @@ int main( int argc, char **argv ) // *((int *)0) = 0; // Check if comm logging is to be enabled: - #ifdef _DEBUG for (int i = 0; i < argc; i++) { if ( @@ -243,7 +240,6 @@ int main( int argc, char **argv ) g_ShouldLogComm = true; } } - #endif // _DEBUG #if !defined(ANDROID_NDK) try -- cgit v1.2.3 From 314fc3cdac702a44a257ada5fab52f0a7d37ffcd Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 14:42:26 +0000 Subject: Mob bugfixes * Mobs no longer require constant line-of-sight to a player to remain aggravated * Fixed an ASSERT * Fixed mobs jumping * Fixed Idle state not properly using AI + Added FILE_IO_PREFIX to favicon loading + Implemented #563 --- src/Generating/ChunkGenerator.cpp | 2 ++ src/Mobs/Monster.cpp | 49 +++++++++++++++++++++++---------------- src/Mobs/Monster.h | 12 ++++++++-- src/Server.cpp | 2 +- src/World.cpp | 13 +++++++++-- src/World.h | 2 +- 6 files changed, 54 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index 27210f49d..ef38f1399 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -223,6 +223,8 @@ void cChunkGenerator::Execute(void) if (m_Queue.empty()) { + // Sometimes the queue remains empty + // If so, we can't do any front() operations on it! continue; } diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 1db16ab71..9ba18f4d1 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -259,6 +259,17 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) if (m_bMovingToDestination) { + if (m_bOnGround) + { + int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); + + if (DoesPosYRequireJump(NextHeight)) + { + m_bOnGround = false; + AddPosY(1.5); // Jump!! + } + } + Vector3f Distance = m_Destination - GetPosition(); if(!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move { @@ -285,17 +296,6 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) TickPathFinding(); // We have reached the next point in our path, calculate another point } } - - if(m_bOnGround) - { - int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); - - if (IsNextYPosReachable(NextHeight)) - { - m_bOnGround = false; - SetSpeedY(5.f); // Jump!! - } - } } if (ReachedFinalDestination()) @@ -373,6 +373,11 @@ int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ) { int PosY = (int)floor(GetPosY()); + if (PosY < 0) + PosY = 0; + else if (PosY > cChunkDef::Height) + PosY = cChunkDef::Height; + if (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))]) { while (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))] && (PosY > 0)) @@ -494,7 +499,7 @@ void cMonster::KilledBy(cEntity * a_Killer) void cMonster::CheckEventSeePlayer(void) { // TODO: Rewrite this to use cWorld's DoWithPlayers() - cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance, false); if (Closest != NULL) { @@ -548,6 +553,11 @@ void cMonster::EventLosePlayer(void) void cMonster::InStateIdle(float a_Dt) { + if (m_bMovingToDestination) + { + return; // Still getting there + } + m_IdleInterval += a_Dt; if (m_IdleInterval > 1) @@ -557,20 +567,19 @@ void cMonster::InStateIdle(float a_Dt) m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds Vector3d Dist; - Dist.x = (double)m_World->GetTickRandomNumber(m_SightDistance * 2) - m_SightDistance; - Dist.z = (double)m_World->GetTickRandomNumber(m_SightDistance * 2) - m_SightDistance; + Dist.x = (double)m_World->GetTickRandomNumber(10) - 5; + Dist.z = (double)m_World->GetTickRandomNumber(10) - 5; if ((Dist.SqrLength() > 2) && (rem >= 3)) { - m_Destination.x = GetPosX() + Dist.x; - m_Destination.z = GetPosZ() + Dist.z; + Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z); - int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); + int NextHeight = FindFirstNonAirBlockPosition(Destination.x, Destination.z); - if (IsNextYPosReachable(NextHeight + 1)) + if (IsNextYPosReachable(NextHeight)) { - m_Destination.y = (double)NextHeight; - MoveToPosition(m_Destination); + Destination.y = NextHeight; + MoveToPosition(Destination); } } } diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index c8129e63d..d04cb8941 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -168,10 +168,18 @@ protected: If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1 If current Y is solid, goes up to find first nonsolid block, and returns that */ int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ); - /** Returns if a monster can actually reach a given height by jumping */ + /** Returns if a monster can actually reach a given height by jumping or walking */ inline bool IsNextYPosReachable(int a_PosY) { - return (a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1); + return ( + (a_PosY <= (int)floor(GetPosY())) || + DoesPosYRequireJump(a_PosY) + ); + } + /** Returns if a monster can reach a given height by jumping */ + inline bool DoesPosYRequireJump(int a_PosY) + { + return ((a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1)); } /** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */ diff --git a/src/Server.cpp b/src/Server.cpp index 34ee066cb..2774c8b46 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -194,7 +194,7 @@ bool cServer::InitServer(cIniFile & a_SettingsIni) m_PlayerCount = 0; m_PlayerCountDiff = 0; - m_FaviconData = Base64Encode(cFile::ReadWholeFile("favicon.png")); // Will return empty string if file nonexistant; client doesn't mind + m_FaviconData = Base64Encode(cFile::ReadWholeFile(FILE_IO_PREFIX + AString("favicon.png"))); // Will return empty string if file nonexistant; client doesn't mind if (m_bIsConnected) { diff --git a/src/World.cpp b/src/World.cpp index 453a22c2d..514524991 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -234,7 +234,11 @@ cWorld::cWorld(const AString & a_WorldName) : m_WorldName(a_WorldName), m_IniFileName(m_WorldName + "/world.ini"), m_StorageSchema("Default"), +#ifdef _arm_ + m_StorageCompressionFactor(3), +#else m_StorageCompressionFactor(6), +#endif m_IsSpawnExplicitlySet(false), m_WorldAgeSecs(0), m_TimeOfDaySecs(0), @@ -2419,7 +2423,7 @@ bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCa // TODO: This interface is dangerous! -cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit) +cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit, bool a_CheckLineOfSight) { cTracer LineOfSight(this); @@ -2434,7 +2438,12 @@ cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit) if (Distance < ClosestDistance) { - if (!LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length())) + if (a_CheckLineOfSight && !LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length())) + { + ClosestDistance = Distance; + ClosestPlayer = *itr; + } + else { ClosestDistance = Distance; ClosestPlayer = *itr; diff --git a/src/World.h b/src/World.h index 61c7604df..933e3ba6f 100644 --- a/src/World.h +++ b/src/World.h @@ -239,7 +239,7 @@ public: bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << // TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action) - cPlayer * FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit); + cPlayer * FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit, bool a_CheckLineOfSight = true); void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player -- cgit v1.2.3 From d9707a92917308fcf29827e6ca5f577624418a1c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 15:19:56 +0000 Subject: Implemented pickup combining * Fixes FS393 * Part of #131 --- src/Entities/Pickup.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src') diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp index 55c878b57..bfe162b69 100644 --- a/src/Entities/Pickup.cpp +++ b/src/Entities/Pickup.cpp @@ -17,6 +17,51 @@ +class cPickupCombiningCallback : + public cEntityCallback +{ +public: + cPickupCombiningCallback(Vector3d a_Position, cPickup * a_Pickup) : + m_Position(a_Position), + m_Pickup(a_Pickup), + m_FoundMatchingPickup(false) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + if (!a_Entity->IsPickup() || (a_Entity->GetUniqueID() == m_Pickup->GetUniqueID()) || a_Entity->IsDestroyed()) + { + return false; + } + + Vector3d EntityPos = a_Entity->GetPosition(); + double Distance = (EntityPos - m_Position).Length(); + + if ((Distance < 1.2) && ((cPickup *)a_Entity)->GetItem().IsEqual(m_Pickup->GetItem())) + { + m_Pickup->GetItem().AddCount(((cPickup *)a_Entity)->GetItem().m_ItemCount); + a_Entity->Destroy(); + m_FoundMatchingPickup = true; + } + return false; + } + + inline bool FoundMatchingPickup() + { + return m_FoundMatchingPickup; + } + +protected: + bool m_FoundMatchingPickup; + + Vector3d m_Position; + cPickup * m_Pickup; +}; + + + + cPickup::cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, bool IsPlayerCreated, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */) : cEntity(etPickup, a_PosX, a_PosY, a_PosZ, 0.2, 0.2) @@ -83,6 +128,16 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk) return; } } + + if (!IsDestroyed()) // Don't try to combine if someone has tried to combine me + { + cPickupCombiningCallback PickupCombiningCallback(GetPosition(), this); + m_World->ForEachEntity(PickupCombiningCallback); // Not ForEachEntityInChunk, otherwise pickups don't combine across chunk boundaries + if (PickupCombiningCallback.FoundMatchingPickup()) + { + m_World->BroadcastEntityMetadata(*this); + } + } } } } -- cgit v1.2.3 From ca0e51d89c5b3979f38918b3df7e0f9137f251ce Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sat, 25 Jan 2014 19:19:17 +0100 Subject: Added RSA encryption to crypto wrappers. --- src/Crypto.cpp | 34 ++++++++++++++++++++++++++++++++++ src/Crypto.h | 5 +++++ 2 files changed, 39 insertions(+) (limited to 'src') diff --git a/src/Crypto.cpp b/src/Crypto.cpp index 5ad866f34..2045d0385 100644 --- a/src/Crypto.cpp +++ b/src/Crypto.cpp @@ -196,6 +196,40 @@ int cRSAPrivateKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLeng +int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength) +{ + if (a_EncryptedMaxLength < m_Rsa.len) + { + LOGD("%s: Invalid a_EncryptedMaxLength: got %u, exp at least %u", + __FUNCTION__, (unsigned)a_EncryptedMaxLength, (unsigned)(m_Rsa.len) + ); + ASSERT(!"Invalid a_DecryptedMaxLength!"); + return -1; + } + if (a_PlainLength < m_Rsa.len) + { + LOGD("%s: Invalid a_PlainLength: got %u, exp at least %u", + __FUNCTION__, (unsigned)a_PlainLength, (unsigned)(m_Rsa.len) + ); + ASSERT(!"Invalid a_PlainLength!"); + return -1; + } + size_t DecryptedLength; + int res = rsa_pkcs1_encrypt( + &m_Rsa, ctr_drbg_random, &m_Ctr_drbg, RSA_PUBLIC, + a_PlainLength, a_PlainData, a_EncryptedData + ); + if (res != 0) + { + return -1; + } + return (int)DecryptedLength; +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cAESCFBDecryptor: diff --git a/src/Crypto.h b/src/Crypto.h index 6b576f55b..a97f34fbf 100644 --- a/src/Crypto.h +++ b/src/Crypto.h @@ -43,6 +43,11 @@ public: Returns the number of bytes decrypted, or negative number for error. */ int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength); + /** Encrypts the data using RSAES-PKCS#1 algorithm. + Both a_EncryptedData and a_DecryptedData must be at least bytes large. + Returns the number of bytes decrypted, or negative number for error. */ + int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength); + protected: rsa_context m_Rsa; entropy_context m_Entropy; -- cgit v1.2.3 From 60b7f5f23d117d48f230f80371b2adf13b85a09e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 19:00:50 +0000 Subject: Attack() is no longer always called --- src/Mobs/AggressiveMonster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp index a4b3eede1..f2f0c404c 100644 --- a/src/Mobs/AggressiveMonster.cpp +++ b/src/Mobs/AggressiveMonster.cpp @@ -50,9 +50,9 @@ void cAggressiveMonster::InStateChasing(float a_Dt) void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity) { - super::EventSeePlayer(a_Entity); if (!((cPlayer *)a_Entity)->IsGameModeCreative()) { + super::EventSeePlayer(a_Entity); m_EMState = CHASING; } } -- cgit v1.2.3 From 7468ba0f107ed01275f346c87ff5bb265dbbff3d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 19:02:13 +0000 Subject: Implemented fall damage for mobs + Implemented mobile fall damage * Formatting fixes + Defined new Position->Integer macros --- src/Entities/Entity.h | 5 +++++ src/Entities/Player.cpp | 6 ++---- src/Entities/Player.h | 2 +- src/Mobs/Monster.cpp | 31 +++++++++++++++++++++++++++---- src/Mobs/Monster.h | 8 ++++++-- 5 files changed, 41 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index f6fa58bb2..b2edfc2b4 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -29,6 +29,11 @@ return super::GetClass(); \ } +#define POSX_TOINT (int)floor(GetPosX()) +#define POSY_TOINT (int)floor(GetPosY()) +#define POSZ_TOINT (int)floor(GetPosZ()) +#define POS_TOINT Vector3i(POSXTOINT, POSYTOINT, POSZTOINT) + diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 2a5baedb6..71e304967 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -26,8 +26,6 @@ #include "inifile/iniFile.h" #include "json/json.h" -#define float2int(x) ((x)<0 ? ((int)(x))-1 : (int)(x)) - @@ -440,7 +438,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround) cWorld * World = GetWorld(); if ((GetPosY() >= 0) && (GetPosY() < cChunkDef::Height)) { - BLOCKTYPE BlockType = World->GetBlock(float2int(GetPosX()), float2int(GetPosY()), float2int(GetPosZ())); + BLOCKTYPE BlockType = World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())); if (BlockType != E_BLOCK_AIR) { m_bTouchGround = true; @@ -470,7 +468,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround) TakeDamage(dtFalling, NULL, Damage, Damage, 0); } - // Mojang uses floor() to get X and Z positions, instead of just casting it to an (int) + // Fall particles GetWorld()->BroadcastSoundParticleEffect(2006, (int)floor(GetPosX()), (int)GetPosY() - 1, (int)floor(GetPosZ()), Damage /* Used as particle effect speed modifier */); } diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 449df978f..50f7560d6 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -415,7 +415,7 @@ protected: float m_LastBlockActionTime; int m_LastBlockActionCnt; eGameMode m_GameMode; - std::string m_IP; + AString m_IP; /// The item being dragged by the cursor while in a UI window cItem m_DraggingItem; diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 9ba18f4d1..42c7d2899 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -82,6 +82,7 @@ cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString , m_AttackRange(2) , m_AttackInterval(0) , m_BurnsInDaylight(false) + , m_LastGroundHeight(POSY_TOINT) { if (!a_ConfigName.empty()) { @@ -113,7 +114,7 @@ void cMonster::TickPathFinding() std::vector m_PotentialCoordinates; m_TraversedCoordinates.push_back(Vector3i(PosX, PosY, PosZ)); - static const struct // Define which directions the torch can power + static const struct // Define which directions to try to move to { int x, z; } gCrossCoords[] = @@ -261,9 +262,9 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) { if (m_bOnGround) { - int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); + m_Destination.y = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); - if (DoesPosYRequireJump(NextHeight)) + if (DoesPosYRequireJump(m_Destination.y)) { m_bOnGround = false; AddPosY(1.5); // Jump!! @@ -298,10 +299,11 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) } } - if (ReachedFinalDestination()) + if (ReachedFinalDestination() && (m_Target != NULL)) Attack(a_Dt); SetPitchAndYawFromDestination(); + HandleFalling(); switch (m_EMState) { @@ -369,6 +371,27 @@ void cMonster::SetPitchAndYawFromDestination() +void cMonster::HandleFalling() +{ + if (m_bOnGround) + { + int Damage = (m_LastGroundHeight - POSY_TOINT) - 3; + + if (Damage > 0) + { + TakeDamage(dtFalling, NULL, Damage, Damage, 0); + + // Fall particles + GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, POSY_TOINT - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */); + } + + m_LastGroundHeight = (int)floor(GetPosY()); + } +} + + + + int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ) { int PosY = (int)floor(GetPosY()); diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index d04cb8941..1dd302cdc 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -199,9 +199,13 @@ protected: /** Sets the body yaw and head yaw/pitch based on next/ultimate destinations */ void SetPitchAndYawFromDestination(void); - /* ===========================*/ + /* =========================== */ + /* ========= FALLING ========= */ - + virtual void HandleFalling(void); + int m_LastGroundHeight; + + /* =========================== */ float m_IdleInterval; float m_DestroyTimer; -- cgit v1.2.3 From 6fa3a0cf70bd631fe809c006e5b315199086cc59 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 19:05:44 +0000 Subject: Two minor changes --- src/ClientHandle.cpp | 2 +- src/Entities/Player.cpp | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 18e3d560e..68bf28af7 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -620,7 +620,7 @@ void cClientHandle::HandleCommandBlockMessage(const char* a_Data, unsigned int a } else { - SendChat(Printf("%s[INFO]%s Command blocks are not enabled on this server", cChatColor::Green.c_str(), cChatColor::White.c_str())); + SendChat(Printf("%s[INFO]%s Command blocks are not enabled on this server", cChatColor::Yellow.c_str(), cChatColor::White.c_str())); } } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 71e304967..82e31ae65 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -463,10 +463,8 @@ void cPlayer::SetTouchGround(bool a_bTouchGround) if (Damage > 0) { - if (!IsGameModeCreative()) - { - TakeDamage(dtFalling, NULL, Damage, Damage, 0); - } + // cPlayer makes sure damage isn't applied in creative, no need to check here + TakeDamage(dtFalling, NULL, Damage, Damage, 0); // Fall particles GetWorld()->BroadcastSoundParticleEffect(2006, (int)floor(GetPosX()), (int)GetPosY() - 1, (int)floor(GetPosZ()), Damage /* Used as particle effect speed modifier */); @@ -790,7 +788,7 @@ void cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI) { if (IsGameModeCreative()) { - // No damage / health in creative mode + // No damage / health in creative mode if not void damage return; } } -- cgit v1.2.3 From 1d0e1bdcb12e648ba2b0b6d54a8bdba4bcaad1d5 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 19:36:20 +0000 Subject: Improved AllToLua UI experience --- src/Bindings/AllToLua.bat | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Bindings/AllToLua.bat b/src/Bindings/AllToLua.bat index b2a192880..f9bcbda45 100644 --- a/src/Bindings/AllToLua.bat +++ b/src/Bindings/AllToLua.bat @@ -4,18 +4,24 @@ :: When called without any parameters, it will pause for a keypress at the end :: Call with any parameter to disable the wait (for buildserver use) +@echo off + :: Regenerate the files: -"tolua++.exe" -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg +echo Regenerating LUA bindings... +"tolua++.exe" -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg >nul : Wait for keypress, if no param given: -if %ALLTOLUA_WAIT%N == N pause +echo Bindings were generated +echo. +echo Please depress the 'any' key to continue +if %ALLTOLUA_WAIT%N == N pause >nul -- cgit v1.2.3 From 7b8dc01db32be3d780f38ffbe788500f82983d62 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sat, 25 Jan 2014 21:19:52 +0100 Subject: Implemented sheeps eating grass. --- src/Mobs/Sheep.cpp | 39 ++++++++++++++++++++++++++++++++++++++- src/Mobs/Sheep.h | 3 +++ 2 files changed, 41 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index bda4ccff8..702108ae4 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -13,7 +13,8 @@ cSheep::cSheep(int a_Color) : super("Sheep", mtSheep, "mob.sheep.say", "mob.sheep.say", 0.6, 1.3), m_IsSheared(false), - m_WoolColor(a_Color) + m_WoolColor(a_Color), + m_TimeToStopEating(-1) { } @@ -60,3 +61,39 @@ void cSheep::OnRightClicked(cPlayer & a_Player) m_World->BroadcastEntityMetadata(*this); } } + + + + + +void cSheep::Tick(float a_Dt, cChunk & a_Chunk) +{ + // The sheep should not move when he's eating so only handle the physics. + if (m_TimeToStopEating > 0) + { + HandlePhysics(a_Dt, a_Chunk); + m_TimeToStopEating--; + if (m_TimeToStopEating == 0) + { + if (m_World->GetBlock((int) GetPosX(), (int) GetPosY() - 1, (int) GetPosZ()) == E_BLOCK_GRASS) + { + // The sheep ate the grass so we change it to dirt. + m_World->SetBlock((int) GetPosX(), (int) GetPosY() - 1, (int) GetPosZ(), E_BLOCK_DIRT, 0); + m_IsSheared = false; + m_World->BroadcastEntityMetadata(*this); + } + } + } + else + { + super::Tick(a_Dt, a_Chunk); + if (m_World->GetTickRandomNumber(600) == 1) + { + if (m_World->GetBlock((int) GetPosX(), (int) GetPosY() - 1, (int) GetPosZ()) == E_BLOCK_GRASS) + { + m_World->BroadcastEntityStatus(*this, 10); + m_TimeToStopEating = 40; + } + } + } +} diff --git a/src/Mobs/Sheep.h b/src/Mobs/Sheep.h index 8293a2c05..4eee3db1c 100644 --- a/src/Mobs/Sheep.h +++ b/src/Mobs/Sheep.h @@ -19,6 +19,8 @@ public: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + bool IsSheared(void) const { return m_IsSheared; } int GetFurColor(void) const { return m_WoolColor; } @@ -26,6 +28,7 @@ private: bool m_IsSheared; int m_WoolColor; + int m_TimeToStopEating; } ; -- cgit v1.2.3 From 398e159f5f3c913079b0f89c6bf4f5fa41466307 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 20:33:23 +0000 Subject: Rail speed tweak --- src/Entities/Minecart.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 78ec017cd..a650927b1 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -416,8 +416,8 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) { // Initialise to 'slow down' values - int AccelDecelSpeed = -1; - int AccelDecelNegSpeed = 1; + int AccelDecelSpeed = -2; + int AccelDecelNegSpeed = 2; if ((a_RailMeta & 0x8) == 0x8) { -- cgit v1.2.3 From cdd6478ceacb7cf5bab8f425390372fca7883a1e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 21:29:27 +0000 Subject: Did what xoft recommended --- src/Mobs/Creeper.cpp | 6 +++++- src/World.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Mobs/Creeper.cpp b/src/Mobs/Creeper.cpp index ad8fe10a1..2e1ece865 100644 --- a/src/Mobs/Creeper.cpp +++ b/src/Mobs/Creeper.cpp @@ -89,4 +89,8 @@ void cCreeper::Attack(float a_Dt) m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this); Destroy(); } -} \ No newline at end of file +} + + + + diff --git a/src/World.cpp b/src/World.cpp index 514524991..5205c2616 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -235,7 +235,7 @@ cWorld::cWorld(const AString & a_WorldName) : m_IniFileName(m_WorldName + "/world.ini"), m_StorageSchema("Default"), #ifdef _arm_ - m_StorageCompressionFactor(3), + m_StorageCompressionFactor(0), #else m_StorageCompressionFactor(6), #endif -- cgit v1.2.3 From 52f7467fe1d0c9ce68259b43cf6f74227318dda8 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 25 Jan 2014 23:48:48 +0000 Subject: Reduced unnecessary echoes (thanks xoft) --- src/Bindings/AllToLua.bat | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Bindings/AllToLua.bat b/src/Bindings/AllToLua.bat index f9bcbda45..f085af9e9 100644 --- a/src/Bindings/AllToLua.bat +++ b/src/Bindings/AllToLua.bat @@ -11,17 +11,15 @@ :: Regenerate the files: -echo Regenerating LUA bindings... -"tolua++.exe" -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg >nul +echo Regenerating LUA bindings . . . +"tolua++.exe" -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg : Wait for keypress, if no param given: -echo Bindings were generated echo. -echo Please depress the 'any' key to continue -if %ALLTOLUA_WAIT%N == N pause >nul +if %ALLTOLUA_WAIT%N == N pause -- cgit v1.2.3 From 70113b57309060b785b070bb2a0075801bc4d844 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 26 Jan 2014 00:14:00 +0000 Subject: Fixed segmentation fault on villager damage It occurred when attack was environmental. --- src/Mobs/Villager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 7f89fb6cc..c8ff4f101 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -21,7 +21,7 @@ cVillager::cVillager(eVillagerType VillagerType) : void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) { super::DoTakeDamage(a_TDI); - if (a_TDI.Attacker->IsPlayer()) + if ((a_TDI.Attacker != NULL) && a_TDI.Attacker->IsPlayer()) { if (m_World->GetTickRandomNumber(5) == 3) { -- cgit v1.2.3 From a533386144f234dcfb61ad6bc5341712ea244afd Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sun, 26 Jan 2014 13:07:21 +0100 Subject: Small fix since the new AI and a new small feature. You get particles when trying to tame wolfs. They don't walk anymore when they are sitting. --- src/Mobs/Wolf.cpp | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 11e3f690a..217834eb1 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -75,10 +75,12 @@ void cWolf::OnRightClicked(cPlayer & a_Player) SetIsTame(true); SetOwner(a_Player.GetName()); m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMED); + m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); } else { m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMING); + m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); } } } @@ -122,7 +124,8 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); } - + + // The wolf is sitting so don't move him at all. if (IsSitting()) { m_bMovingToDestination = false; @@ -145,8 +148,18 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk) SetIsBegging(true); m_World->BroadcastEntityMetadata(*this); } - m_FinalDestination = a_Closest_Player->GetPosition();; - m_bMovingToDestination = false; + // Don't move to the player if the wolf is sitting. + if (IsSitting()) + { + m_bMovingToDestination = false; + } + else + { + m_bMovingToDestination = true; + } + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + PlayerPos.y++; + m_FinalDestination = PlayerPos; break; } default: @@ -185,15 +198,23 @@ void cWolf::TickFollowPlayer() } Callback; if (m_World->DoWithPlayer(m_OwnerName, Callback)) { - // The player is present in the world, follow them: + // The player is present in the world, follow him: double Distance = (Callback.OwnerPos - GetPosition()).Length(); - if ((Distance > 30) && (!IsSitting())) + if (Distance > 30) { TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z); } else { - MoveToPosition(Callback.OwnerPos); + m_FinalDestination = Callback.OwnerPos; + if (IsSitting()) + { + m_bMovingToDestination = false; + } + else + { + m_bMovingToDestination = true; + } } } } -- cgit v1.2.3 From 4c780e7b4490c34694e9f76e6944d5959299eb84 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sun, 26 Jan 2014 13:27:35 +0100 Subject: Fixed bug where wolfs would teleport while they were sitting. --- src/Mobs/Wolf.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 217834eb1..c0c7892e3 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -202,7 +202,10 @@ void cWolf::TickFollowPlayer() double Distance = (Callback.OwnerPos - GetPosition()).Length(); if (Distance > 30) { - TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z); + if (!IsSitting()) + { + TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z); + } } else { -- cgit v1.2.3