From ea9de4bbb70192626b00a810482671cf14bd7f8c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 26 Jan 2014 16:15:05 +0000 Subject: Added SIGABRT to catchers list --- src/main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 06b344c25..0f6895d03 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -68,9 +68,10 @@ void NonCtrlHandler(int a_Signal) LOGERROR("Details | SIGABRT: Server self-terminated due to an internal fault"); break; } + case SIGINT: case SIGTERM: { - std::signal(SIGTERM, SIG_IGN); // Server is shutting down, wait for it... + std::signal(a_Signal, SIG_IGN); // Server is shutting down, wait for it... break; } default: break; @@ -224,6 +225,10 @@ int main( int argc, char **argv ) std::signal(SIGSEGV, NonCtrlHandler); std::signal(SIGTERM, NonCtrlHandler); std::signal(SIGINT, NonCtrlHandler); + std::signal(SIGABRT, NonCtrlHandler); + #ifdef SIGABRT_COMPAT + std::signal(SIGABRT_COMPAT, NonCtrlHandler); + #endif // SIGABRT_COMPAT #endif // DEBUG: test the dumpfile creation: -- cgit v1.2.3 From a3ac1be7b7ed48dbaadc57650a17161fc18a5e84 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 26 Jan 2014 14:42:25 +0100 Subject: Fixed Byte-order reading. The functions would fail on bytes that were above 127. --- src/StringUtils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp index 0dbd41c12..3fe75d611 100644 --- a/src/StringUtils.cpp +++ b/src/StringUtils.cpp @@ -833,7 +833,8 @@ AString Base64Encode(const AString & a_Input) short GetBEShort(const char * a_Mem) { - return (((short)a_Mem[0]) << 8) | a_Mem[1]; + const Byte * Bytes = (const Byte *)a_Mem; + return (Bytes[0] << 8) | Bytes[1]; } @@ -842,7 +843,8 @@ short GetBEShort(const char * a_Mem) int GetBEInt(const char * a_Mem) { - return (((int)a_Mem[0]) << 24) | (((int)a_Mem[1]) << 16) | (((int)a_Mem[2]) << 8) | a_Mem[3]; + const Byte * Bytes = (const Byte *)a_Mem; + return (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | Bytes[3]; } -- cgit v1.2.3 From 61848ff5a0866a8e14f81c12ab85088dfe460708 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 26 Jan 2014 14:43:54 +0100 Subject: Item-loading now checks for weird bytes. --- src/WorldStorage/WSSAnvil.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index e2a882f65..a0f9136d8 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -611,12 +611,18 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx) { - int ID = a_NBT.FindChildByName(a_TagIdx, "id"); - if ((ID < 0) || (a_NBT.GetType(ID) != TAG_Short)) + int Type = a_NBT.FindChildByName(a_TagIdx, "id"); + if ((Type < 0) || (a_NBT.GetType(Type) != TAG_Short)) { return false; } - a_Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID)); + a_Item.m_ItemType = a_NBT.GetShort(Type); + if (a_Item.m_ItemType < 0) + { + LOGD("Encountered an item with negative type (%d). Replacing with an empty item.", a_NBT.GetShort(Type)); + a_Item.Empty(); + return true; + } int Damage = a_NBT.FindChildByName(a_TagIdx, "Damage"); if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short)) -- cgit v1.2.3 From ab4672be40f0576ab90418e11043d686de6c5855 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 26 Jan 2014 17:48:09 +0100 Subject: cByteBuffer has more self-tests. --- src/ByteBuffer.cpp | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index e06f63a0e..d2d3beb97 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -54,6 +54,7 @@ public: { TestRead(); TestWrite(); + TestWrap(); } void TestRead(void) @@ -61,11 +62,11 @@ public: cByteBuffer buf(50); buf.Write("\x05\xac\x02\x00", 4); UInt32 v1; - ASSERT(buf.ReadVarInt(v1) && (v1 == 5)); + assert(buf.ReadVarInt(v1) && (v1 == 5)); UInt32 v2; - ASSERT(buf.ReadVarInt(v2) && (v2 == 300)); + assert(buf.ReadVarInt(v2) && (v2 == 300)); UInt32 v3; - ASSERT(buf.ReadVarInt(v3) && (v3 == 0)); + assert(buf.ReadVarInt(v3) && (v3 == 0)); } void TestWrite(void) @@ -76,9 +77,30 @@ public: buf.WriteVarInt(0); AString All; buf.ReadAll(All); - ASSERT(All.size() == 4); - ASSERT(memcmp(All.data(), "\x05\xac\x02\x00", All.size()) == 0); + assert(All.size() == 4); + assert(memcmp(All.data(), "\x05\xac\x02\x00", All.size()) == 0); } + + void TestWrap(void) + { + cByteBuffer buf(3); + for (int i = 0; i < 1000; i++) + { + int FreeSpace = buf.GetFreeSpace(); + assert(buf.GetReadableSpace() == 0); + assert(FreeSpace > 0); + assert(buf.Write("a", 1)); + assert(buf.CanReadBytes(1)); + assert(buf.GetReadableSpace() == 1); + unsigned char v = 0; + assert(buf.ReadByte(v)); + assert(v == 'a'); + assert(buf.GetReadableSpace() == 0); + buf.CommitRead(); + assert(buf.GetFreeSpace() == FreeSpace); // We're back to normal + } + } + } g_ByteBufferTest; #endif @@ -159,7 +181,7 @@ bool cByteBuffer::Write(const char * a_Bytes, int a_Count) int CurReadableSpace = GetReadableSpace(); int WrittenBytes = 0; - if (GetFreeSpace() < a_Count) + if (CurFreeSpace < a_Count) { return false; } @@ -864,3 +886,4 @@ void cByteBuffer::CheckValid(void) const + -- cgit v1.2.3 From 30c431b479673b2c94b9d642fc7de73679cf3e6f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 26 Jan 2014 17:54:18 +0100 Subject: Fixed client packet parsing. When the packet wouldn't fit the current buffer, the server would mis-parse the next packet. This was the cause for #541. Also modified comm logging, now each direction can be turned on separately. --- src/Protocol/Protocol17x.cpp | 45 ++++++++++++++++++++++++++++++++------------ src/main.cpp | 26 ++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 9bb2cfbf0..0d349de03 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -54,7 +54,7 @@ Implements the 1.7.x protocol classes: // fwd: main.cpp: -extern bool g_ShouldLogComm; +extern bool g_ShouldLogCommIn, g_ShouldLogCommOut; @@ -74,7 +74,7 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd m_IsEncrypted(false) { // Create the comm log file, if so requested: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn || g_ShouldLogCommOut) { cFile::CreateFolder("CommLogs"); AString FileName = Printf("CommLogs/%x__%s.log", (unsigned)time(NULL), a_Client->GetIPString().c_str()); @@ -1083,7 +1083,7 @@ 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: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn) { if (m_ReceivedData.GetReadableSpace() > 0) { @@ -1092,9 +1092,10 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) m_ReceivedData.ReadAll(AllData); m_ReceivedData.ResetRead(); m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace); + ASSERT(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", + m_CommLogFile.Printf("Incoming data, %d (0x%x) unparsed bytes already present in buffer:\n%s\n", AllData.size(), AllData.size(), Hex.c_str() ); } @@ -1103,6 +1104,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) m_CommLogFile.Printf("Incoming data: %d (0x%x) bytes: \n%s\n", a_Size, a_Size, Hex.c_str() ); + m_CommLogFile.Flush(); } if (!m_ReceivedData.Write(a_Data, a_Size)) @@ -1119,12 +1121,14 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) if (!m_ReceivedData.ReadVarInt(PacketLen)) { // Not enough data - return; + m_ReceivedData.ResetRead(); + break; } if (!m_ReceivedData.CanReadBytes(PacketLen)) { // The full packet hasn't been received yet - return; + m_ReceivedData.ResetRead(); + break; } cByteBuffer bb(PacketLen + 1); VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); @@ -1137,11 +1141,11 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) if (!bb.ReadVarInt(PacketType)) { // Not enough data - return; + break; } // Log the packet info into the comm log file: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn) { AString PacketData; bb.ReadAll(PacketData); @@ -1173,7 +1177,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) #endif // _DEBUG // Put a message in the comm log: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn) { m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n"); } @@ -1189,7 +1193,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) ); // Put a message in the comm log: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn) { m_CommLogFile.Printf("^^^^^^ Wrong number of bytes read for this packet (exp %d left, got %d left) ^^^^^^\n\n\n", 1, bb.GetReadableSpace() @@ -1200,7 +1204,24 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) ASSERT(!"Read wrong number of bytes!"); m_Client->PacketError(PacketType); } - } // while (true) + } // for(ever) + + // Log any leftover bytes into the logfile: + if (g_ShouldLogCommIn && (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); + ASSERT(m_ReceivedData.GetReadableSpace() == OldReadableSpace); + AString Hex; + CreateHexDump(Hex, AllData.data(), AllData.size(), 16); + m_CommLogFile.Printf("There are %d (0x%x) bytes of non-parse-able data left in the buffer:\n%s", + m_ReceivedData.GetReadableSpace(), m_ReceivedData.GetReadableSpace(), Hex.c_str() + ); + m_CommLogFile.Flush(); + } } @@ -1881,7 +1902,7 @@ cProtocol172::cPacketizer::~cPacketizer() m_Out.CommitRead(); // Log the comm into logfile: - if (g_ShouldLogComm) + if (g_ShouldLogCommOut) { AString Hex; ASSERT(DataToSend.size() > 0); diff --git a/src/main.cpp b/src/main.cpp index 0f6895d03..9acc7db3a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,8 +19,11 @@ bool g_SERVER_TERMINATED = false; // Set to true when the server terminates, so -/** If set to true, the protocols will log each player's communication to a separate logfile */ -bool g_ShouldLogComm; +/** If set to true, the protocols will log each player's incoming (C->S) communication to a per-connection logfile */ +bool g_ShouldLogCommIn; + +/** If set to true, the protocols will log each player's outgoing (S->C) communication to a per-connection logfile */ +bool g_ShouldLogCommOut; @@ -242,7 +245,24 @@ int main( int argc, char **argv ) (NoCaseCompare(argv[i], "/logcomm") == 0) ) { - g_ShouldLogComm = true; + g_ShouldLogCommIn = true; + g_ShouldLogCommOut = true; + } + if ( + (NoCaseCompare(argv[i], "/commlogin") == 0) || + (NoCaseCompare(argv[i], "/comminlog") == 0) || + (NoCaseCompare(argv[i], "/logcommin") == 0) + ) + { + g_ShouldLogCommIn = true; + } + if ( + (NoCaseCompare(argv[i], "/commlogout") == 0) || + (NoCaseCompare(argv[i], "/commoutlog") == 0) || + (NoCaseCompare(argv[i], "/logcommout") == 0) + ) + { + g_ShouldLogCommOut = true; } } -- cgit v1.2.3 From ed95f4d81b3f54111430aec00d429aff267dfa92 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 14:40:31 +0100 Subject: Makes farmers farm crops. --- src/Mobs/Villager.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/Mobs/Villager.h | 5 ++++ 2 files changed, 76 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index c8ff4f101..0bf87157a 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -3,6 +3,8 @@ #include "Villager.h" #include "../World.h" +#include "../Blockarea.h" +#include "../Blocks/BlockHandler.h" @@ -10,7 +12,8 @@ cVillager::cVillager(eVillagerType VillagerType) : super("Villager", mtVillager, "", "", 0.6, 1.8), - m_Type(VillagerType) + m_Type(VillagerType), + m_DidFindCrops(false) { } @@ -33,3 +36,70 @@ void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) + +void cVillager::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + if (m_DidFindCrops) + { + Vector3i Pos = Vector3i(GetPosition()); + std::cout << Pos.Equals(m_CropsPos) << "\n"; + if (Pos.Equals(m_CropsPos)) + { + cBlockHandler Handler(E_BLOCK_CROPS); + Handler.DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + m_DidFindCrops = false; + } + } + + if (m_World->GetTickRandomNumber(50) != 0) + { + return; + } + + switch (m_Type) + { + case vtFarmer: + { + HandleFarmer(); + } + } + +} + + + + +void cVillager::HandleFarmer() +{ + cBlockArea Surrounding; + Surrounding.Read(m_World, + (int) GetPosX() - 5, + (int) GetPosX() + 5, + (int) GetPosY() - 3, + (int) GetPosY() + 3, + (int) GetPosZ() - 5, + (int) GetPosZ() + 5); + + // Check for crops in a 10x6x10 area. + for (int X = 0; X < 10; X++) + { + for (int Y = 0; Y < 6; Y++) + { + for (int Z = 0; Z < 10; Z++) + { + if (Surrounding.GetRelBlockType(X, Y, Z) == E_BLOCK_CROPS && Surrounding.GetRelBlockMeta(X, Y, Z) == 0x7) + { + m_DidFindCrops = true; + m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); + MoveToPosition(Vector3f((float) GetPosX() + X - 5, (float) GetPosY() + Y - 3, (float) GetPosZ() + Z - 5)); + return; + } + } + } + } +} + + + + diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index 4cd9aaa8e..b7cbe8ed0 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -30,11 +30,16 @@ public: CLASS_PROTODEF(cVillager); virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual void Tick (float a_Dt, cChunk & a_Chunk) override; + + void HandleFarmer(); int GetVilType(void) const { return m_Type; } private: int m_Type; + bool m_DidFindCrops; + Vector3i m_CropsPos; } ; -- cgit v1.2.3 From 969bf05a2686a24ccae6838d2cb9b3b2a0c55111 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 15:44:55 +0100 Subject: Villagers: Farmers can also harvest carrots and potatoes. --- src/Mobs/Villager.cpp | 46 +++++++++++++++++++++++++++++++++++++--------- src/Mobs/Villager.h | 1 + 2 files changed, 38 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 0bf87157a..71907f6b7 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -43,11 +43,19 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) if (m_DidFindCrops) { Vector3i Pos = Vector3i(GetPosition()); - std::cout << Pos.Equals(m_CropsPos) << "\n"; if (Pos.Equals(m_CropsPos)) { - cBlockHandler Handler(E_BLOCK_CROPS); - Handler.DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) + { + cItems Pickups; + //Pickups.Add(E_ITEM_WHEAT, 1, 0); + //Pickups.Add(E_ITEM_SEEDS, 1 + m_World->GetTickRandomNumber( + cBlockHandler Handler(CropBlock); + Handler.ConvertToPickups(Pickups, 0x7); + m_World->SpawnItemPickups(Pickups, m_CropsPos.x + 0.5, m_CropsPos.y + 0.5, m_CropsPos.z + 0.5); + m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); + } m_DidFindCrops = false; } } @@ -64,7 +72,6 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) HandleFarmer(); } } - } @@ -88,13 +95,19 @@ void cVillager::HandleFarmer() { for (int Z = 0; Z < 10; Z++) { - if (Surrounding.GetRelBlockType(X, Y, Z) == E_BLOCK_CROPS && Surrounding.GetRelBlockMeta(X, Y, Z) == 0x7) + if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z))) { - m_DidFindCrops = true; - m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); - MoveToPosition(Vector3f((float) GetPosX() + X - 5, (float) GetPosY() + Y - 3, (float) GetPosZ() + Z - 5)); - return; + continue; } + if (Surrounding.GetRelBlockMeta(X, Y, Z) != 0x7) + { + continue; + } + + m_DidFindCrops = true; + m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); + MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) (m_CropsPos.y), (float) (m_CropsPos.z + 0.5))); + return; } } } @@ -103,3 +116,18 @@ void cVillager::HandleFarmer() + +bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType) +{ + switch (a_BlockType) + { + case E_BLOCK_CROPS: + case E_BLOCK_POTATOES: + case E_BLOCK_CARROTS: + { + return true; + } + } + return false; +} + diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index b7cbe8ed0..9502f387c 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -33,6 +33,7 @@ public: virtual void Tick (float a_Dt, cChunk & a_Chunk) override; void HandleFarmer(); + bool IsBlockFarmable(BLOCKTYPE a_BlockType); int GetVilType(void) const { return m_Type; } private: -- cgit v1.2.3 From 89a620ca54bbeb9475ded781ef7af145571ab01a Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 17:19:13 +0100 Subject: E_BLOCK_POTATOES isn't an solid block. Villagers were floating above them. --- src/BlockID.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/BlockID.cpp b/src/BlockID.cpp index 095865d07..fbb5a0720 100644 --- a/src/BlockID.cpp +++ b/src/BlockID.cpp @@ -767,6 +767,7 @@ public: g_BlockIsSolid[E_BLOCK_MELON_STEM] = false; g_BlockIsSolid[E_BLOCK_NETHER_PORTAL] = false; g_BlockIsSolid[E_BLOCK_PISTON_EXTENSION] = false; + g_BlockIsSolid[E_BLOCK_POTATOES] = false; g_BlockIsSolid[E_BLOCK_POWERED_RAIL] = false; g_BlockIsSolid[E_BLOCK_RAIL] = false; g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_OFF] = false; -- cgit v1.2.3 From ca12decaf60bc7d6a32ee45c1a796edcde076e86 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 17:20:39 +0100 Subject: Villagers don't look for new crops when they already found one. Slight cleanup. --- src/Mobs/Villager.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 71907f6b7..b42c3ecaa 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -40,24 +40,19 @@ void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); - if (m_DidFindCrops) + if (m_DidFindCrops && !m_bMovingToDestination) { - Vector3i Pos = Vector3i(GetPosition()); - if (Pos.Equals(m_CropsPos)) + if ((GetPosition() - m_CropsPos).Length() < 2) { BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) { - cItems Pickups; - //Pickups.Add(E_ITEM_WHEAT, 1, 0); - //Pickups.Add(E_ITEM_SEEDS, 1 + m_World->GetTickRandomNumber( cBlockHandler Handler(CropBlock); - Handler.ConvertToPickups(Pickups, 0x7); - m_World->SpawnItemPickups(Pickups, m_CropsPos.x + 0.5, m_CropsPos.y + 0.5, m_CropsPos.z + 0.5); + Handler.DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); } - m_DidFindCrops = false; } + m_DidFindCrops = false; } if (m_World->GetTickRandomNumber(50) != 0) @@ -69,7 +64,10 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { case vtFarmer: { - HandleFarmer(); + if (!m_DidFindCrops) + { + HandleFarmer(); + } } } } @@ -106,7 +104,7 @@ void cVillager::HandleFarmer() m_DidFindCrops = true; m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); - MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) (m_CropsPos.y), (float) (m_CropsPos.z + 0.5))); + MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5))); return; } } -- cgit v1.2.3 From 2cdd8f1961252da2723e7a1047e91ec4914eef57 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 17:30:18 +0100 Subject: Villagers: Fixed only gettings the crops block when farming. --- src/Mobs/Villager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index b42c3ecaa..4d358e0a6 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -47,8 +47,8 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) { - cBlockHandler Handler(CropBlock); - Handler.DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + cBlockHandler * Handler = cBlockHandler::GetBlockHandler(CropBlock); + Handler->DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); } } -- cgit v1.2.3 From 06c3bc1ea5e20c3ddc88f66631f675523789f398 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 18:27:57 +0100 Subject: Villagers: Farmers now replant the crops. --- src/Mobs/Villager.cpp | 17 ++++++++++++++++- src/Mobs/Villager.h | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 4d358e0a6..f52d60ffa 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -13,7 +13,8 @@ cVillager::cVillager(eVillagerType VillagerType) : super("Villager", mtVillager, "", "", 0.6, 1.8), m_Type(VillagerType), - m_DidFindCrops(false) + m_DidFindCrops(false), + m_ActionCountDown(-1) { } @@ -40,6 +41,19 @@ void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); + if (m_ActionCountDown > -1) + { + m_ActionCountDown--; + if (m_ActionCountDown == 0) + { + switch (m_Type) + { + case vtFarmer: m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); + } + } + return; + } + if (m_DidFindCrops && !m_bMovingToDestination) { if ((GetPosition() - m_CropsPos).Length() < 2) @@ -50,6 +64,7 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) cBlockHandler * Handler = cBlockHandler::GetBlockHandler(CropBlock); Handler->DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); + m_ActionCountDown = 20; } } m_DidFindCrops = false; diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index 9502f387c..bdbcab39b 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -38,6 +38,7 @@ public: private: + int m_ActionCountDown; int m_Type; bool m_DidFindCrops; Vector3i m_CropsPos; -- cgit v1.2.3 From 9807056a9cfcce00cf5c33ce6eae25f818ec9cf7 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 18:33:57 +0100 Subject: Added GetCropsPos and DidFindCrops functions. --- src/Mobs/Villager.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index bdbcab39b..235e1f40e 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -29,12 +29,18 @@ public: CLASS_PROTODEF(cVillager); + // Override functions virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void Tick (float a_Dt, cChunk & a_Chunk) override; + // cVillager functions void HandleFarmer(); bool IsBlockFarmable(BLOCKTYPE a_BlockType); + + // Get and set functions. int GetVilType(void) const { return m_Type; } + Vector3i GetCropsPos(void) const { return m_CropsPos; } + bool DidFindCrops(void) const { return m_DidFindCrops; } private: -- cgit v1.2.3 From 3dbe6c6de941873461951fc2fa8dc1be9d199768 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 18:58:09 +0100 Subject: Villager: Farmer: Crops finding is more random. --- src/Mobs/Villager.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index f52d60ffa..31e6e87a0 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -101,29 +101,30 @@ void cVillager::HandleFarmer() (int) GetPosZ() - 5, (int) GetPosZ() + 5); - // Check for crops in a 10x6x10 area. - for (int X = 0; X < 10; X++) + + for (int I = 0; I < 5; I++) { for (int Y = 0; Y < 6; Y++) { - for (int Z = 0; Z < 10; Z++) + // Pick random coordinates and check for crops. + int X = m_World->GetTickRandomNumber(11); + int Z = m_World->GetTickRandomNumber(11); + + if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z))) { - if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z))) - { - continue; - } - if (Surrounding.GetRelBlockMeta(X, Y, Z) != 0x7) - { - continue; - } - - m_DidFindCrops = true; - m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); - MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5))); - return; + continue; } - } - } + if (Surrounding.GetRelBlockMeta(X, Y, Z) != 0x7) + { + continue; + } + + m_DidFindCrops = true; + m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); + MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5))); + return; + } // for Y loop. + } // Repeat the procces 5 times. } -- cgit v1.2.3 From 9cf006eceafac87aa7fc5d74ee3eed3740f95b60 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 19:06:50 +0100 Subject: Fixed compiler error. --- 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 31e6e87a0..ef362b559 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -3,7 +3,7 @@ #include "Villager.h" #include "../World.h" -#include "../Blockarea.h" +#include "../BlockArea.h" #include "../Blocks/BlockHandler.h" -- cgit v1.2.3 From fc9e5278304adf811becf90e62311c1318e9658d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 27 Jan 2014 18:57:14 +0000 Subject: SIGABRT exits with failure. --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 9acc7db3a..c8cd2d4fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,6 +69,7 @@ void NonCtrlHandler(int a_Signal) std::signal(a_Signal, SIG_DFL); LOGERROR(" D: | MCServer has encountered an error and needs to close"); LOGERROR("Details | SIGABRT: Server self-terminated due to an internal fault"); + exit(EXIT_FAILURE); break; } case SIGINT: -- cgit v1.2.3 From 5b983b72fa0508fee5135153c9273f5e37fb5467 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 20:44:18 +0100 Subject: Villager: Farmers can't place crops on blocks other then farmland. --- src/Mobs/Villager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index ef362b559..5d6d7482f 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -48,7 +48,13 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { switch (m_Type) { - case vtFarmer: m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); + case vtFarmer: + { + if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) + { + m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); + } + } } } return; -- cgit v1.2.3 From 723bb78dd144a34adae5502b4d526ab887b911d5 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 20:52:42 +0100 Subject: Villagers: Harvesting is more rare. --- 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 5d6d7482f..46346fa9f 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -76,7 +76,7 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) m_DidFindCrops = false; } - if (m_World->GetTickRandomNumber(50) != 0) + if (m_World->GetTickRandomNumber(100) != 0) { return; } -- cgit v1.2.3 From cc1284a753874aa7d351a6ea41aaec4662ca6e57 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 27 Jan 2014 21:27:13 +0100 Subject: Rewritten networking to use non-blocking sockets. This fixes #592. --- src/OSSupport/Socket.cpp | 31 +++++++- src/OSSupport/Socket.h | 9 +++ src/OSSupport/SocketThreads.cpp | 172 +++++++++++++++++++++++++++------------- src/OSSupport/SocketThreads.h | 26 ++++-- 4 files changed, 176 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/OSSupport/Socket.cpp b/src/OSSupport/Socket.cpp index 4226a7535..3248eed88 100644 --- a/src/OSSupport/Socket.cpp +++ b/src/OSSupport/Socket.cpp @@ -320,7 +320,7 @@ bool cSocket::ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Por -int cSocket::Receive(char* a_Buffer, unsigned int a_Length, unsigned int a_Flags) +int cSocket::Receive(char * a_Buffer, unsigned int a_Length, unsigned int a_Flags) { return recv(m_Socket, a_Buffer, a_Length, a_Flags); } @@ -354,3 +354,32 @@ unsigned short cSocket::GetPort(void) const + +void cSocket::SetNonBlocking(void) +{ + #ifdef _WIN32 + u_long NonBlocking = 1; + int res = ioctlsocket(m_Socket, FIONBIO, &NonBlocking); + if (res != 0) + { + LOGERROR("Cannot set socket to non-blocking. This would make the server deadlock later on, aborting.\nErr: %d, %d, %s", + res, GetLastError(), GetLastErrorString().c_str() + ); + abort(); + } + #else + int NonBlocking = 1; + int res = ioctl(m_Socket, FIONBIO, (char *)&NonBlocking); + if (res != 0) + { + LOGERROR("Cannot set socket to non-blocking. This would make the server deadlock later on, aborting.\nErr: %d, %d, %s", + res, GetLastError(), GetLastErrorString().c_str() + ); + abort(); + } + #endif +} + + + + diff --git a/src/OSSupport/Socket.h b/src/OSSupport/Socket.h index 4ca3d61f4..bdc2babf5 100644 --- a/src/OSSupport/Socket.h +++ b/src/OSSupport/Socket.h @@ -24,6 +24,12 @@ public: { IPv4 = AF_INET, IPv6 = AF_INET6, + + #ifdef _WIN32 + ErrWouldBlock = WSAEWOULDBLOCK, + #else + ErrWouldBlock = EWOULDBLOCK, + #endif } ; #ifdef _WIN32 @@ -110,6 +116,9 @@ public: unsigned short GetPort(void) const; // Returns 0 on failure const AString & GetIPString(void) const { return m_IPString; } + + /** Sets the socket into non-blocking mode */ + void SetNonBlocking(void); private: xSocket m_Socket; diff --git a/src/OSSupport/SocketThreads.cpp b/src/OSSupport/SocketThreads.cpp index 74932daf8..3e2631733 100644 --- a/src/OSSupport/SocketThreads.cpp +++ b/src/OSSupport/SocketThreads.cpp @@ -175,6 +175,7 @@ void cSocketThreads::cSocketThread::AddClient(const cSocket & a_Socket, cCallbac m_Slots[m_NumSlots].m_Client = a_Client; m_Slots[m_NumSlots].m_Socket = a_Socket; + m_Slots[m_NumSlots].m_Socket.SetNonBlocking(); m_Slots[m_NumSlots].m_Outgoing.clear(); m_Slots[m_NumSlots].m_State = sSlot::ssNormal; m_NumSlots++; @@ -213,7 +214,9 @@ bool cSocketThreads::cSocketThread::RemoveClient(const cCallback * a_Client) else { // Query and queue the last batch of outgoing data: - m_Slots[i].m_Client->GetOutgoingData(m_Slots[i].m_Outgoing); + AString Data; + m_Slots[i].m_Client->GetOutgoingData(Data); + m_Slots[i].m_Outgoing.append(Data); if (m_Slots[i].m_Outgoing.empty()) { // No more outgoing data, shut the socket down immediately: @@ -386,38 +389,28 @@ void cSocketThreads::cSocketThread::Execute(void) // The main thread loop: while (!m_ShouldTerminate) { - // Put all sockets into the Read set: + // Read outgoing data from the clients: + QueueOutgoingData(); + + // Put sockets into the sets fd_set fdRead; + fd_set fdWrite; cSocket::xSocket Highest = m_ControlSocket1.GetSocket(); - - PrepareSet(&fdRead, Highest, false); + PrepareSets(&fdRead, &fdWrite, Highest); // Wait for the sockets: timeval Timeout; Timeout.tv_sec = 5; Timeout.tv_usec = 0; - if (select(Highest + 1, &fdRead, NULL, NULL, &Timeout) == -1) + if (select(Highest + 1, &fdRead, &fdWrite, NULL, &Timeout) == -1) { - LOG("select(R) call failed in cSocketThread: \"%s\"", cSocket::GetLastErrorString().c_str()); + LOG("select() call failed in cSocketThread: \"%s\"", cSocket::GetLastErrorString().c_str()); continue; } + // Perform the IO: ReadFromSockets(&fdRead); - - // Test sockets for writing: - fd_set fdWrite; - Highest = m_ControlSocket1.GetSocket(); - PrepareSet(&fdWrite, Highest, true); - Timeout.tv_sec = 0; - Timeout.tv_usec = 0; - if (select(Highest + 1, NULL, &fdWrite, NULL, &Timeout) == -1) - { - LOG("select(W) call failed in cSocketThread: \"%s\"", cSocket::GetLastErrorString().c_str()); - continue; - } - WriteToSockets(&fdWrite); - CleanUpShutSockets(); } // while (!mShouldTerminate) } @@ -426,10 +419,11 @@ void cSocketThreads::cSocketThread::Execute(void) -void cSocketThreads::cSocketThread::PrepareSet(fd_set * a_Set, cSocket::xSocket & a_Highest, bool a_IsForWriting) +void cSocketThreads::cSocketThread::PrepareSets(fd_set * a_Read, fd_set * a_Write, cSocket::xSocket & a_Highest) { - FD_ZERO(a_Set); - FD_SET(m_ControlSocket1.GetSocket(), a_Set); + FD_ZERO(a_Read); + FD_ZERO(a_Write); + FD_SET(m_ControlSocket1.GetSocket(), a_Read); cCSLock Lock(m_Parent->m_CS); for (int i = m_NumSlots - 1; i >= 0; --i) @@ -444,11 +438,16 @@ void cSocketThreads::cSocketThread::PrepareSet(fd_set * a_Set, cSocket::xSocket continue; } cSocket::xSocket s = m_Slots[i].m_Socket.GetSocket(); - FD_SET(s, a_Set); + FD_SET(s, a_Read); if (s > a_Highest) { a_Highest = s; } + if (!m_Slots[i].m_Outgoing.empty()) + { + // There's outgoing data for the socket, put it in the Write set + FD_SET(s, a_Write); + } } // for i - m_Slots[] } @@ -480,34 +479,37 @@ void cSocketThreads::cSocketThread::ReadFromSockets(fd_set * a_Read) int Received = m_Slots[i].m_Socket.Receive(Buffer, ARRAYCOUNT(Buffer), 0); if (Received <= 0) { - // The socket has been closed by the remote party - switch (m_Slots[i].m_State) + if (cSocket::GetLastError() != cSocket::ErrWouldBlock) { - case sSlot::ssNormal: - { - // Notify the callback that the remote has closed the socket; keep the slot - m_Slots[i].m_Client->SocketClosed(); - m_Slots[i].m_State = sSlot::ssRemoteClosed; - break; - } - case sSlot::ssWritingRestOut: - case sSlot::ssShuttingDown: - case sSlot::ssShuttingDown2: - { - // Force-close the socket and remove the slot: - m_Slots[i].m_Socket.CloseSocket(); - m_Slots[i] = m_Slots[--m_NumSlots]; - break; - } - default: + // The socket has been closed by the remote party + switch (m_Slots[i].m_State) { - LOG("%s: Unexpected socket state: %d (%s)", - __FUNCTION__, m_Slots[i].m_Socket.GetSocket(), m_Slots[i].m_Socket.GetIPString().c_str() - ); - ASSERT(!"Unexpected socket state"); - break; - } - } // switch (m_Slots[i].m_State) + case sSlot::ssNormal: + { + // Notify the callback that the remote has closed the socket; keep the slot + m_Slots[i].m_Client->SocketClosed(); + m_Slots[i].m_State = sSlot::ssRemoteClosed; + break; + } + case sSlot::ssWritingRestOut: + case sSlot::ssShuttingDown: + case sSlot::ssShuttingDown2: + { + // Force-close the socket and remove the slot: + m_Slots[i].m_Socket.CloseSocket(); + m_Slots[i] = m_Slots[--m_NumSlots]; + break; + } + default: + { + LOG("%s: Unexpected socket state: %d (%s)", + __FUNCTION__, m_Slots[i].m_Socket.GetSocket(), m_Slots[i].m_Socket.GetIPString().c_str() + ); + ASSERT(!"Unexpected socket state"); + break; + } + } // switch (m_Slots[i].m_State) + } } else { @@ -539,7 +541,9 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) // Request another chunk of outgoing data: if (m_Slots[i].m_Client != NULL) { - m_Slots[i].m_Client->GetOutgoingData(m_Slots[i].m_Outgoing); + AString Data; + m_Slots[i].m_Client->GetOutgoingData(Data); + m_Slots[i].m_Outgoing.append(Data); } if (m_Slots[i].m_Outgoing.empty()) { @@ -553,8 +557,7 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) } } // if (outgoing data is empty) - int Sent = m_Slots[i].m_Socket.Send(m_Slots[i].m_Outgoing.data(), m_Slots[i].m_Outgoing.size()); - if (Sent < 0) + if (!SendDataThroughSocket(m_Slots[i].m_Socket, m_Slots[i].m_Outgoing)) { int Err = cSocket::GetLastError(); LOGWARNING("Error %d while writing to client \"%s\", disconnecting. \"%s\"", Err, m_Slots[i].m_Socket.GetIPString().c_str(), GetOSErrorString(Err).c_str()); @@ -565,7 +568,6 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) } return; } - m_Slots[i].m_Outgoing.erase(0, Sent); if (m_Slots[i].m_Outgoing.empty() && (m_Slots[i].m_State == sSlot::ssWritingRestOut)) { @@ -590,8 +592,41 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) +bool cSocketThreads::cSocketThread::SendDataThroughSocket(cSocket & a_Socket, AString & a_Data) +{ + // Send data in smaller chunks, so that the OS send buffers aren't overflown easily + while (!a_Data.empty()) + { + size_t NumToSend = std::min(a_Data.size(), (size_t)1024); + int Sent = a_Socket.Send(a_Data.data(), NumToSend); + if (Sent < 0) + { + int Err = cSocket::GetLastError(); + if (Err == cSocket::ErrWouldBlock) + { + // The OS send buffer is full, leave the outgoing data for the next time + return true; + } + // An error has occured + return false; + } + if (Sent == 0) + { + a_Socket.CloseSocket(); + return true; + } + a_Data.erase(0, Sent); + } + return true; +} + + + + + void cSocketThreads::cSocketThread::CleanUpShutSockets(void) { + cCSLock Lock(m_Parent->m_CS); for (int i = m_NumSlots - 1; i >= 0; i--) { switch (m_Slots[i].m_State) @@ -617,3 +652,32 @@ void cSocketThreads::cSocketThread::CleanUpShutSockets(void) +void cSocketThreads::cSocketThread::QueueOutgoingData(void) +{ + cCSLock Lock(m_Parent->m_CS); + for (int i = 0; i < m_NumSlots; i++) + { + if (m_Slots[i].m_Client != NULL) + { + AString Data; + m_Slots[i].m_Client->GetOutgoingData(Data); + m_Slots[i].m_Outgoing.append(Data); + } + if (m_Slots[i].m_Outgoing.empty()) + { + // No outgoing data is ready + if (m_Slots[i].m_State == sSlot::ssWritingRestOut) + { + // The socket doesn't want to be kept alive anymore, and doesn't have any remaining data to send. + // Shut it down and then close it after a timeout, or when the other side agrees + m_Slots[i].m_State = sSlot::ssShuttingDown; + m_Slots[i].m_Socket.ShutdownReadWrite(); + } + continue; + } + } +} + + + + diff --git a/src/OSSupport/SocketThreads.h b/src/OSSupport/SocketThreads.h index 9e1947ab6..fcd2ce11f 100644 --- a/src/OSSupport/SocketThreads.h +++ b/src/OSSupport/SocketThreads.h @@ -66,7 +66,8 @@ public: /** Called when data is received from the remote party */ virtual void DataReceived(const char * a_Data, int a_Size) = 0; - /** Called when data can be sent to remote party; the function is supposed to *append* outgoing data to a_Data */ + /** Called when data can be sent to remote party + The function is supposed to *set* outgoing data to a_Data (overwrite) */ virtual void GetOutgoingData(AString & a_Data) = 0; /** Called when the socket has been closed for any reason */ @@ -156,16 +157,27 @@ private: virtual void Execute(void) override; - /** Puts all sockets into the set, along with m_ControlSocket1. - Only sockets that are able to send and receive data are put in the Set. - Is a_IsForWriting is true, the ssWritingRestOut sockets are added as well. */ - void PrepareSet(fd_set * a_Set, cSocket::xSocket & a_Highest, bool a_IsForWriting); + /** Prepares the Read and Write socket sets for select() + Puts all sockets into the read set, along with m_ControlSocket1. + Only sockets that have outgoing data queued on them are put in the write set.*/ + void PrepareSets(fd_set * a_ReadSet, fd_set * a_WriteSet, cSocket::xSocket & a_Highest); - void ReadFromSockets(fd_set * a_Read); // Reads from sockets indicated in a_Read - void WriteToSockets (fd_set * a_Write); // Writes to sockets indicated in a_Write + /** Reads from sockets indicated in a_Read */ + void ReadFromSockets(fd_set * a_Read); + /** Writes to sockets indicated in a_Write */ + void WriteToSockets (fd_set * a_Write); + + /** Sends data through the specified socket, trying to fill the OS send buffer in chunks. + Returns true if there was no error while sending, false if an error has occured. + Modifies a_Data to contain only the unsent data. */ + bool SendDataThroughSocket(cSocket & a_Socket, AString & a_Data); + /** Removes those slots in ssShuttingDown2 state, sets those with ssShuttingDown state to ssShuttingDown2 */ void CleanUpShutSockets(void); + + /** Calls each client's callback to retrieve outgoing data for that client. */ + void QueueOutgoingData(void); } ; typedef std::list cSocketThreadList; -- cgit v1.2.3 From 4169af1ce1a022d364edfa3313aa5a21d594f198 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 27 Jan 2014 21:33:06 +0100 Subject: Fixed Linux compilation. --- src/OSSupport/Socket.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/OSSupport/Socket.cpp b/src/OSSupport/Socket.cpp index 3248eed88..064abbab5 100644 --- a/src/OSSupport/Socket.cpp +++ b/src/OSSupport/Socket.cpp @@ -6,7 +6,8 @@ #ifndef _WIN32 #include #include - #include //inet_ntoa() + #include // inet_ntoa() + #include // ioctl() #else #define socklen_t int #endif -- cgit v1.2.3 From 33ad2761a0acb79ce938ebf518a731264617c03d Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 21:34:22 +0100 Subject: Cleanup Most code in Tick is now split up in different functions. --- src/Mobs/Villager.cpp | 86 ++++++++++++++++++++++++++++++++++----------------- src/Mobs/Villager.h | 10 ++++-- 2 files changed, 65 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 46346fa9f..e39d8bc1f 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -13,7 +13,7 @@ cVillager::cVillager(eVillagerType VillagerType) : super("Villager", mtVillager, "", "", 0.6, 1.8), m_Type(VillagerType), - m_DidFindCrops(false), + m_VillagerAction(false), m_ActionCountDown(-1) { } @@ -50,33 +50,33 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { case vtFarmer: { - if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) - { - m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); - } + HandleFarmerNoCountDown(); } } } return; } - if (m_DidFindCrops && !m_bMovingToDestination) + if (m_VillagerAction) { - if ((GetPosition() - m_CropsPos).Length() < 2) + switch (m_Type) { - BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); - if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) + case vtFarmer: { - cBlockHandler * Handler = cBlockHandler::GetBlockHandler(CropBlock); - Handler->DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); - m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); - m_ActionCountDown = 20; + HandleFarmerAction(); } } - m_DidFindCrops = false; + m_VillagerAction = false; } - if (m_World->GetTickRandomNumber(100) != 0) + // The villager already has an special action activated. + if (m_VillagerAction) + { + return; + } + + // Don't always try to do a special action. Each tick has 1% to do a special action. + if (m_World->GetTickRandomNumber(99) != 0) { return; } @@ -85,10 +85,7 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { case vtFarmer: { - if (!m_DidFindCrops) - { - HandleFarmer(); - } + HandleFarmerAttemptSpecialAction(); } } } @@ -96,16 +93,19 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) -void cVillager::HandleFarmer() +void cVillager::HandleFarmerAttemptSpecialAction() { cBlockArea Surrounding; - Surrounding.Read(m_World, - (int) GetPosX() - 5, - (int) GetPosX() + 5, - (int) GetPosY() - 3, - (int) GetPosY() + 3, - (int) GetPosZ() - 5, - (int) GetPosZ() + 5); + /// Read a 11x7x11 area. + Surrounding.Read( + m_World, + (int) GetPosX() - 5, + (int) GetPosX() + 5, + (int) GetPosY() - 3, + (int) GetPosY() + 3, + (int) GetPosZ() - 5, + (int) GetPosZ() + 5 + ); for (int I = 0; I < 5; I++) @@ -125,7 +125,7 @@ void cVillager::HandleFarmer() continue; } - m_DidFindCrops = true; + m_VillagerAction = true; m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5); MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5))); return; @@ -137,6 +137,36 @@ void cVillager::HandleFarmer() +void cVillager::HandleFarmerAction() +{ + if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2) + { + BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) + { + cBlockHandler * Handler = cBlockHandler::GetBlockHandler(CropBlock); + Handler->DropBlock(m_World, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); + m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0); + m_ActionCountDown = 20; + } + } +} + + + + +void cVillager::HandleFarmerNoCountDown() +{ + if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) + { + m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); + } +} + + + + + bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType) { switch (a_BlockType) diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index 235e1f40e..20dbada61 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -34,19 +34,23 @@ public: virtual void Tick (float a_Dt, cChunk & a_Chunk) override; // cVillager functions - void HandleFarmer(); bool IsBlockFarmable(BLOCKTYPE a_BlockType); + // Farmer functions + void HandleFarmerAttemptSpecialAction(); + void HandleFarmerAction(); + void HandleFarmerNoCountDown(); + // Get and set functions. int GetVilType(void) const { return m_Type; } Vector3i GetCropsPos(void) const { return m_CropsPos; } - bool DidFindCrops(void) const { return m_DidFindCrops; } + bool DoesHaveActionActivated(void) const { return m_VillagerAction; } private: int m_ActionCountDown; int m_Type; - bool m_DidFindCrops; + bool m_VillagerAction; Vector3i m_CropsPos; } ; -- cgit v1.2.3 From a359275064ecbaf3608995e82875532419a8ed80 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 27 Jan 2014 21:34:54 +0100 Subject: Squashed common code. --- src/OSSupport/Socket.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/OSSupport/Socket.cpp b/src/OSSupport/Socket.cpp index 064abbab5..6afaceedf 100644 --- a/src/OSSupport/Socket.cpp +++ b/src/OSSupport/Socket.cpp @@ -361,24 +361,17 @@ void cSocket::SetNonBlocking(void) #ifdef _WIN32 u_long NonBlocking = 1; int res = ioctlsocket(m_Socket, FIONBIO, &NonBlocking); - if (res != 0) - { - LOGERROR("Cannot set socket to non-blocking. This would make the server deadlock later on, aborting.\nErr: %d, %d, %s", - res, GetLastError(), GetLastErrorString().c_str() - ); - abort(); - } #else int NonBlocking = 1; int res = ioctl(m_Socket, FIONBIO, (char *)&NonBlocking); - if (res != 0) - { - LOGERROR("Cannot set socket to non-blocking. This would make the server deadlock later on, aborting.\nErr: %d, %d, %s", - res, GetLastError(), GetLastErrorString().c_str() - ); - abort(); - } #endif + if (res != 0) + { + LOGERROR("Cannot set socket to non-blocking. This would make the server deadlock later on, aborting.\nErr: %d, %d, %s", + res, GetLastError(), GetLastErrorString().c_str() + ); + abort(); + } } -- cgit v1.2.3 From 8bf9043f98900a870c18389fe367e156da6b9f6c Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 21:39:00 +0100 Subject: Villager: Few more comments. --- src/Mobs/Villager.cpp | 11 ++++++++--- src/Mobs/Villager.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index e39d8bc1f..262f13a99 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -50,7 +50,7 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { case vtFarmer: { - HandleFarmerNoCountDown(); + HandleFarmerEndCountDown(); } } } @@ -93,6 +93,8 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) +//////////////////////////////////////////////////////////////////////////////// +// Farmer functions. void cVillager::HandleFarmerAttemptSpecialAction() { cBlockArea Surrounding; @@ -107,7 +109,6 @@ void cVillager::HandleFarmerAttemptSpecialAction() (int) GetPosZ() + 5 ); - for (int I = 0; I < 5; I++) { for (int Y = 0; Y < 6; Y++) @@ -116,6 +117,7 @@ void cVillager::HandleFarmerAttemptSpecialAction() int X = m_World->GetTickRandomNumber(11); int Z = m_World->GetTickRandomNumber(11); + // A villager can't farm this. if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z))) { continue; @@ -139,8 +141,10 @@ void cVillager::HandleFarmerAttemptSpecialAction() void cVillager::HandleFarmerAction() { + // Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks. if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2) { + // Check if the blocks didn't change while the villager was walking to the coordinates. BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z); if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7) { @@ -155,8 +159,9 @@ void cVillager::HandleFarmerAction() -void cVillager::HandleFarmerNoCountDown() +void cVillager::HandleFarmerEndCountDown() { + // Check if there is still farmland at the spot where the crops were. if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) { m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0); diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index 20dbada61..979d2a3ac 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -39,7 +39,7 @@ public: // Farmer functions void HandleFarmerAttemptSpecialAction(); void HandleFarmerAction(); - void HandleFarmerNoCountDown(); + void HandleFarmerEndCountDown(); // Get and set functions. int GetVilType(void) const { return m_Type; } -- cgit v1.2.3 From babc80ed777f2ee74ce770d95bd3ec5743370570 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 22:02:19 +0100 Subject: The world can now be configured wether farmers should be able to harvest crops. --- src/Mobs/Villager.cpp | 10 ++++++++++ src/World.cpp | 1 + src/World.h | 3 +++ 3 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 262f13a99..74a2a6d99 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -141,6 +141,11 @@ void cVillager::HandleFarmerAttemptSpecialAction() void cVillager::HandleFarmerAction() { + if (!m_World->VillagersShouldHarvestCrops()) + { + return; + } + // Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks. if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2) { @@ -161,6 +166,11 @@ void cVillager::HandleFarmerAction() void cVillager::HandleFarmerEndCountDown() { + if (!m_World->VillagersShouldHarvestCrops()) + { + return; + } + // Check if there is still farmland at the spot where the crops were. if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) { diff --git a/src/World.cpp b/src/World.cpp index 5205c2616..88bbf5f8a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -547,6 +547,7 @@ void cWorld::Start(void) m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", false); m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true); m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false); + m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true); m_GameMode = (eGameMode)IniFile.GetValueSetI("GameMode", "GameMode", m_GameMode); diff --git a/src/World.h b/src/World.h index d7a7241d1..4d5659ee6 100644 --- a/src/World.h +++ b/src/World.h @@ -138,6 +138,8 @@ public: bool ShouldLavaSpawnFire(void) const { return m_ShouldLavaSpawnFire; } + bool VillagersShouldHarvestCrops(void) const { return m_VillagersShouldHarvestCrops; } + eDimension GetDimension(void) const { return m_Dimension; } /** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */ @@ -743,6 +745,7 @@ private: bool m_bEnabledPVP; bool m_IsDeepSnowEnabled; bool m_ShouldLavaSpawnFire; + bool m_VillagersShouldHarvestCrops; std::vector m_BlockTickQueue; std::vector m_BlockTickQueueCopy; // Second is for safely removing the objects from the queue -- cgit v1.2.3 From 807a4dba989ad397c5f624f0a245df55103ee117 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 27 Jan 2014 22:04:24 +0100 Subject: Villager doesn't check the environment for crops if it doesn't need to. --- src/Mobs/Villager.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 74a2a6d99..4a3cce26e 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -97,6 +97,11 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) // Farmer functions. void cVillager::HandleFarmerAttemptSpecialAction() { + if (!m_World->VillagersShouldHarvestCrops()) + { + return; + } + cBlockArea Surrounding; /// Read a 11x7x11 area. Surrounding.Read( -- cgit v1.2.3 From 81837edb22197b48c3da4c47954681096a867766 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 28 Jan 2014 09:50:48 +0100 Subject: Fixed a slight bug in RSA encryption code. --- src/Crypto.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/Crypto.cpp b/src/Crypto.cpp index 2045d0385..540b5cfde 100644 --- a/src/Crypto.cpp +++ b/src/Crypto.cpp @@ -214,7 +214,6 @@ int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte 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 @@ -223,7 +222,7 @@ int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte { return -1; } - return (int)DecryptedLength; + return (int)m_Rsa.len; } -- cgit v1.2.3 From b2bacf3a25001ed855319d6f2146a3d5e734f43c Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 28 Jan 2014 15:40:13 +0100 Subject: Villager: NoCountDown and Action function don't check VillagersShouldHarvestCrops anymore because it shoudn't even be activated anywhere. --- src/Mobs/Villager.cpp | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 4a3cce26e..021d4c672 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -146,11 +146,6 @@ void cVillager::HandleFarmerAttemptSpecialAction() void cVillager::HandleFarmerAction() { - if (!m_World->VillagersShouldHarvestCrops()) - { - return; - } - // Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks. if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2) { @@ -171,11 +166,6 @@ void cVillager::HandleFarmerAction() void cVillager::HandleFarmerEndCountDown() { - if (!m_World->VillagersShouldHarvestCrops()) - { - return; - } - // Check if there is still farmland at the spot where the crops were. if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) { -- cgit v1.2.3 From 8ca98e0c0e09706561ed54cf8be95a731157a59e Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 28 Jan 2014 16:26:44 +0100 Subject: Renamed Farmer functions and added doxycomments --- src/Mobs/Villager.cpp | 18 +++++++----------- src/Mobs/Villager.h | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 021d4c672..44ec14295 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -41,6 +41,7 @@ void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); + if (m_ActionCountDown > -1) { m_ActionCountDown--; @@ -50,7 +51,7 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { case vtFarmer: { - HandleFarmerEndCountDown(); + HandleFarmerPlaceCrops(); } } } @@ -63,15 +64,10 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { case vtFarmer: { - HandleFarmerAction(); + HandleFarmerTryHarvestCrops(); } } m_VillagerAction = false; - } - - // The villager already has an special action activated. - if (m_VillagerAction) - { return; } @@ -85,7 +81,7 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) { case vtFarmer: { - HandleFarmerAttemptSpecialAction(); + HandleFarmerPrepareFarmCrops(); } } } @@ -95,7 +91,7 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk) //////////////////////////////////////////////////////////////////////////////// // Farmer functions. -void cVillager::HandleFarmerAttemptSpecialAction() +void cVillager::HandleFarmerPrepareFarmCrops() { if (!m_World->VillagersShouldHarvestCrops()) { @@ -144,7 +140,7 @@ void cVillager::HandleFarmerAttemptSpecialAction() -void cVillager::HandleFarmerAction() +void cVillager::HandleFarmerTryHarvestCrops() { // Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks. if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2) @@ -164,7 +160,7 @@ void cVillager::HandleFarmerAction() -void cVillager::HandleFarmerEndCountDown() +void cVillager::HandleFarmerPlaceCrops() { // Check if there is still farmland at the spot where the crops were. if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND) diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index 979d2a3ac..b99ae876f 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -34,17 +34,24 @@ public: virtual void Tick (float a_Dt, cChunk & a_Chunk) override; // cVillager functions + /** return true if the given blocktype are: crops, potatoes or carrots.*/ bool IsBlockFarmable(BLOCKTYPE a_BlockType); + ////////////////////////////////////////////////////////////////// // Farmer functions - void HandleFarmerAttemptSpecialAction(); - void HandleFarmerAction(); - void HandleFarmerEndCountDown(); + /** It searches in a 11x7x11 area for crops. If it found some it will navigate to them.*/ + void HandleFarmerPrepareFarmCrops(); + + /** Looks if the farmer has reached it's destination, and if it's still crops and the destination is closer then 2 blocks it will harvest them.*/ + void HandleFarmerTryHarvestCrops(); + + /** Replaces the crops he harvested.*/ + void HandleFarmerPlaceCrops(); // Get and set functions. - int GetVilType(void) const { return m_Type; } - Vector3i GetCropsPos(void) const { return m_CropsPos; } - bool DoesHaveActionActivated(void) const { return m_VillagerAction; } + int GetVilType(void) const { return m_Type; } + Vector3i GetCropsPos(void) const { return m_CropsPos; } + bool DoesHaveActionActivated(void) const { return m_VillagerAction; } private: -- cgit v1.2.3 From 76457d367338b603808b7821036cf9edc6f95afb Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 28 Jan 2014 16:28:55 +0100 Subject: Fixed timing on *nix. --- src/OSSupport/Timer.cpp | 2 +- src/Root.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/OSSupport/Timer.cpp b/src/OSSupport/Timer.cpp index ed16f9e3a..fd838dd0d 100644 --- a/src/OSSupport/Timer.cpp +++ b/src/OSSupport/Timer.cpp @@ -28,7 +28,7 @@ long long cTimer::GetNowTime(void) #else struct timeval now; gettimeofday(&now, NULL); - return (long long)(now.tv_sec * 1000 + now.tv_usec / 1000); + return (long long)now.tv_sec * 1000 + (long long)now.tv_usec / 1000; #endif } diff --git a/src/Root.cpp b/src/Root.cpp index fa1fdb37a..883bfe76e 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -200,7 +200,7 @@ void cRoot::Start(void) long long finishmseconds = Time.GetNowTime(); finishmseconds -= mseconds; - LOG("Startup complete, took %i ms!", finishmseconds); + LOG("Startup complete, took %lld ms!", finishmseconds); #ifdef _WIN32 EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button #endif -- cgit v1.2.3 From f7cbb07b54e3cafdef7578693ea5340fcaf9ac3d Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 28 Jan 2014 23:15:04 +0100 Subject: Fixed an error in Crypto. --- src/Crypto.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Crypto.cpp b/src/Crypto.cpp index 540b5cfde..6f7047ab0 100644 --- a/src/Crypto.cpp +++ b/src/Crypto.cpp @@ -206,7 +206,7 @@ int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte ASSERT(!"Invalid a_DecryptedMaxLength!"); return -1; } - if (a_PlainLength < m_Rsa.len) + if (a_EncryptedMaxLength < m_Rsa.len) { LOGD("%s: Invalid a_PlainLength: got %u, exp at least %u", __FUNCTION__, (unsigned)a_PlainLength, (unsigned)(m_Rsa.len) @@ -215,7 +215,7 @@ int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte return -1; } int res = rsa_pkcs1_encrypt( - &m_Rsa, ctr_drbg_random, &m_Ctr_drbg, RSA_PUBLIC, + &m_Rsa, ctr_drbg_random, &m_Ctr_drbg, RSA_PRIVATE, a_PlainLength, a_PlainData, a_EncryptedData ); if (res != 0) -- cgit v1.2.3 From 9de52252acb22104584ff7a0746ee81734c3f19e Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 28 Jan 2014 23:38:56 +0100 Subject: Crypto: Added public key encryption / decryption. --- src/Crypto.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/Crypto.h | 31 ++++++++++++++++++++++++ 2 files changed, 106 insertions(+) (limited to 'src') diff --git a/src/Crypto.cpp b/src/Crypto.cpp index 6f7047ab0..7a06d7fa3 100644 --- a/src/Crypto.cpp +++ b/src/Crypto.cpp @@ -229,6 +229,81 @@ int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cPublicKey: + +cPublicKey::cPublicKey(const AString & a_PublicKeyDER) +{ + pk_init(&m_Pk); + if (pk_parse_public_key(&m_Pk, (const Byte *)a_PublicKeyDER.data(), a_PublicKeyDER.size()) != 0) + { + ASSERT(!"Cannot parse PubKey"); + return; + } + InitRnd(); +} + + + + + +cPublicKey::~cPublicKey() +{ + pk_free(&m_Pk); +} + + + + + +int cPublicKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength) +{ + size_t DecryptedLen = a_DecryptedMaxLength; + int res = pk_decrypt(&m_Pk, + a_EncryptedData, a_EncryptedLength, + a_DecryptedData, &DecryptedLen, a_DecryptedMaxLength, + ctr_drbg_random, &m_Ctr_drbg + ); + if (res != 0) + { + return res; + } + return (int)DecryptedLen; +} + + + + + +int cPublicKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength) +{ + size_t EncryptedLength = a_EncryptedMaxLength; + int res = pk_encrypt(&m_Pk, + a_PlainData, a_PlainLength, a_EncryptedData, &EncryptedLength, a_EncryptedMaxLength, + ctr_drbg_random, &m_Ctr_drbg + ); + if (res != 0) + { + return res; + } + return (int)EncryptedLength; +} + + + + + +void cPublicKey::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); +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cAESCFBDecryptor: diff --git a/src/Crypto.h b/src/Crypto.h index a97f34fbf..d68f7ec24 100644 --- a/src/Crypto.h +++ b/src/Crypto.h @@ -14,6 +14,7 @@ #include "polarssl/entropy.h" #include "polarssl/ctr_drbg.h" #include "polarssl/sha1.h" +#include "polarssl/pk.h" @@ -62,6 +63,36 @@ protected: +class cPublicKey +{ +public: + cPublicKey(const AString & a_PublicKeyDER); + ~cPublicKey(); + + /** Decrypts the data using the stored public key + 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); + + /** Encrypts the data using the stored public key + 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: + pk_context m_Pk; + 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 { -- cgit v1.2.3 From bc6fc859f4c245d17d3bbc2028d93b42b1232d01 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 28 Jan 2014 23:53:07 +0100 Subject: Protocol 1.7: Forced encryption on all connections. This is for testing purposes only, to find bugs in the encryption. Once the encryption is deemed stable, it will be enabled only for servers with enabled Authentication. --- src/Protocol/Protocol17x.cpp | 102 +++++++++++++++++++++++++++++++++++++++++-- src/Protocol/Protocol17x.h | 2 + src/Server.cpp | 3 +- src/Server.h | 28 +++++++----- 4 files changed, 120 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 0d349de03..267c18a99 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -53,6 +53,12 @@ Implements the 1.7.x protocol classes: +const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... + + + + + // fwd: main.cpp: extern bool g_ShouldLogCommIn, g_ShouldLogCommOut; @@ -1351,7 +1357,64 @@ void cProtocol172::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) void cProtocol172::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) { - // TODO: Add protocol encryption + short EncKeyLength, EncNonceLength; + a_ByteBuffer.ReadBEShort(EncKeyLength); + AString EncKey; + if (!a_ByteBuffer.ReadString(EncKey, EncKeyLength)) + { + return; + } + a_ByteBuffer.ReadBEShort(EncNonceLength); + AString EncNonce; + if (!a_ByteBuffer.ReadString(EncNonce, EncNonceLength)) + { + return; + } + if ((EncKeyLength > MAX_ENC_LEN) || (EncNonceLength > MAX_ENC_LEN)) + { + LOGD("Too long encryption"); + m_Client->Kick("Hacked client"); + return; + } + + // Decrypt EncNonce using privkey + cRSAPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey(); + Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)]; + int res = rsaDecryptor.Decrypt((const Byte *)EncNonce.data(), EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce)); + if (res != 4) + { + LOGD("Bad nonce length: got %d, exp %d", res, 4); + m_Client->Kick("Hacked client"); + return; + } + if (ntohl(DecryptedNonce[0]) != (unsigned)(uintptr_t)this) + { + LOGD("Bad nonce value"); + m_Client->Kick("Hacked client"); + return; + } + + // Decrypt the symmetric encryption key using privkey: + Byte DecryptedKey[MAX_ENC_LEN]; + res = rsaDecryptor.Decrypt((const Byte *)EncKey.data(), EncKey.size(), DecryptedKey, sizeof(DecryptedKey)); + if (res != 16) + { + LOGD("Bad key length"); + m_Client->Kick("Hacked client"); + return; + } + + StartEncryption(DecryptedKey); + + // Send login success: + { + cPacketizer Pkt(*this, 0x02); // Login success packet + Pkt.WriteString(Printf("%d", m_Client->GetUniqueID())); // TODO: proper UUID + Pkt.WriteString(m_Client->GetUsername()); + } + + m_State = 3; // State = Game + m_Client->HandleLogin(4, m_Client->GetUsername()); } @@ -1363,14 +1426,26 @@ void cProtocol172::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) AString Username; a_ByteBuffer.ReadVarUTF8String(Username); - // TODO: Protocol encryption should be set up here if not localhost / auth - if (!m_Client->HandleHandshake(Username)) { // The client is not welcome here, they have been sent a Kick packet already return; } + // If auth is required, then send the encryption request: + // if (cRoot::Get()->GetServer()->ShouldAuthenticate()) + { + cPacketizer Pkt(*this, 0x01); + Pkt.WriteString(cRoot::Get()->GetServer()->GetServerID()); + const AString & PubKeyDer = cRoot::Get()->GetServer()->GetPublicKeyDER(); + Pkt.WriteShort(PubKeyDer.size()); + Pkt.WriteBuf(PubKeyDer.data(), PubKeyDer.size()); + Pkt.WriteShort(4); + Pkt.WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :) + m_Client->SetUsername(Username); + return; + } + // Send login success: { cPacketizer Pkt(*this, 0x02); // Login success packet @@ -1882,6 +1957,27 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) +void cProtocol172::StartEncryption(const Byte * a_Key) +{ + m_Encryptor.Init(a_Key, a_Key); + m_Decryptor.Init(a_Key, a_Key); + m_IsEncrypted = true; + + // Prepare the m_AuthServerID: + cSHA1Checksum Checksum; + const AString & ServerID = cRoot::Get()->GetServer()->GetServerID(); + Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length()); + Checksum.Update(a_Key, 16); + 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); +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cProtocol172::cPacketizer: diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 72544b575..6a75e41c8 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -281,6 +281,8 @@ protected: /// Parses item metadata as read by ReadItem(), into the item enchantments. void ParseItemMetadata(cItem & a_Item, const AString & a_Metadata); + + void StartEncryption(const Byte * a_Key); } ; diff --git a/src/Server.cpp b/src/Server.cpp index 3f9f8a4ac..ba2b46d55 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -237,7 +237,8 @@ bool cServer::InitServer(cIniFile & a_SettingsIni) m_bIsConnected = true; m_ServerID = "-"; - if (a_SettingsIni.GetValueSetB("Authentication", "Authenticate", true)) + m_ShouldAuthenticate = a_SettingsIni.GetValueSetB("Authentication", "Authenticate", true); + if (m_ShouldAuthenticate) { MTRand mtrand1; unsigned int r1 = (mtrand1.randInt() % 1147483647) + 1000000000; diff --git a/src/Server.h b/src/Server.h index 15eafc00a..b5280c59d 100644 --- a/src/Server.h +++ b/src/Server.h @@ -71,13 +71,13 @@ public: // tolua_export bool Command(cClientHandle & a_Client, AString & a_Cmd); - /// Executes the console command, sends output through the specified callback + /** Executes the console command, sends output through the specified callback */ void ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output); - /// Lists all available console commands and their helpstrings + /** Lists all available console commands and their helpstrings */ void PrintHelp(const AStringVector & a_Split, cCommandOutputCallback & a_Output); - /// Binds the built-in console commands with the plugin manager + /** Binds the built-in console commands with the plugin manager */ static void BindBuiltInConsoleCommands(void); void Shutdown(void); @@ -97,13 +97,13 @@ public: // tolua_export void RemoveClient(const cClientHandle * a_Client); // Removes the clienthandle from m_SocketThreads - /// Don't tick a_Client anymore, it will be ticked from its cPlayer instead + /** Don't tick a_Client anymore, it will be ticked from its cPlayer instead */ void ClientMovedToWorld(const cClientHandle * a_Client); - /// Notifies the server that a player was created; the server uses this to adjust the number of players + /** Notifies the server that a player was created; the server uses this to adjust the number of players */ void PlayerCreated(const cPlayer * a_Player); - /// Notifies the server that a player is being destroyed; the server uses this to adjust the number of players + /** Notifies the server that a player is being destroyed; the server uses this to adjust the number of players */ void PlayerDestroying(const cPlayer * a_Player); /** Returns base64 encoded favicon data (obtained from favicon.png) */ @@ -112,11 +112,13 @@ public: // tolua_export cRSAPrivateKey & GetPrivateKey(void) { return m_PrivateKey; } const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; } + bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; } + private: friend class cRoot; // so cRoot can create and destroy cServer - /// When NotifyClientWrite() is called, it is queued for this thread to process (to avoid deadlocks between cSocketThreads, cClientHandle and cChunkMap) + /** When NotifyClientWrite() is called, it is queued for this thread to process (to avoid deadlocks between cSocketThreads, cClientHandle and cChunkMap) */ class cNotifyWriteThread : public cIsThread { @@ -140,7 +142,7 @@ private: void NotifyClientWrite(const cClientHandle * a_Client); } ; - /// The server tick thread takes care of the players who aren't yet spawned in a world + /** The server tick thread takes care of the players who aren't yet spawned in a world */ class cTickThread : public cIsThread { @@ -195,18 +197,22 @@ private: cTickThread m_TickThread; cEvent m_RestartEvent; - /// The server ID used for client authentication + /** The server ID used for client authentication */ AString m_ServerID; + /** If true, players will be online-authenticated agains Mojang servers. + This setting is the same as the "online-mode" setting in Vanilla. */ + bool m_ShouldAuthenticate; + cServer(void); - /// Loads, or generates, if missing, RSA keys for protocol encryption + /** Loads, or generates, if missing, RSA keys for protocol encryption */ void PrepareKeys(void); bool Tick(float a_Dt); - /// Ticks the clients in m_Clients, manages the list in respect to removing clients + /** Ticks the clients in m_Clients, manages the list in respect to removing clients */ void TickClients(float a_Dt); // cListenThread::cCallback overrides: -- cgit v1.2.3 From 3bbca8c29187c2f3c3a23912a25e4c43e57131b2 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 29 Jan 2014 09:56:31 +0100 Subject: Protocol 1.7: Encryption is enabled only with auth. --- src/Protocol/Protocol17x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 267c18a99..0e9759194 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1433,7 +1433,7 @@ void cProtocol172::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) } // If auth is required, then send the encryption request: - // if (cRoot::Get()->GetServer()->ShouldAuthenticate()) + if (cRoot::Get()->GetServer()->ShouldAuthenticate()) { cPacketizer Pkt(*this, 0x01); Pkt.WriteString(cRoot::Get()->GetServer()->GetServerID()); -- cgit v1.2.3 From 789cf6374053dbb5571f26db1c68ec82cdb48740 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 29 Jan 2014 12:16:27 +0100 Subject: Added 1.7.4 to the list of supported protocols. --- src/Protocol/ProtocolRecognizer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index daeed1845..f58c66d10 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -18,7 +18,7 @@ // Adjust these if a new protocol is added or an old one is removed: -#define MCS_CLIENT_VERSIONS "1.2.4, 1.2.5, 1.3.1, 1.3.2, 1.4.2, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.5, 1.5.1, 1.5.2, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.7.2" +#define MCS_CLIENT_VERSIONS "1.2.4, 1.2.5, 1.3.1, 1.3.2, 1.4.2, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.5, 1.5.1, 1.5.2, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.7.2, 1.7.4" #define MCS_PROTOCOL_VERSIONS "29, 39, 47, 49, 51, 60, 61, 73, 74, 77, 78, 4" -- cgit v1.2.3 From 374034e615e6c7aee2f5b0262bcb0548a3093819 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 29 Jan 2014 13:27:03 +0100 Subject: Bottle o' Enchanting spawns an experience orb. --- src/Entities/ProjectileEntity.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp index 12ce9a303..16b832539 100644 --- a/src/Entities/ProjectileEntity.cpp +++ b/src/Entities/ProjectileEntity.cpp @@ -679,7 +679,8 @@ super(pkExpBottle, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25) void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) { - // TODO: Spawn experience orbs + // Spawn an experience orb with a reward between 3 and 11. + m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), 3 + m_World->GetTickRandomNumber(8)); Destroy(); } -- cgit v1.2.3 From 5e3f7947ae1c835d85e5813b7981bebe8014cc8a Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 29 Jan 2014 13:28:08 +0100 Subject: Removed debug message when a firework entity hit a solid block. --- src/Entities/ProjectileEntity.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp index 16b832539..bffa790a3 100644 --- a/src/Entities/ProjectileEntity.cpp +++ b/src/Entities/ProjectileEntity.cpp @@ -711,8 +711,6 @@ void cFireworkEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) SetSpeed(0, 0, 0); SetPosition(GetPosX(), GetPosY() - 0.5, GetPosZ()); - std::cout << a_HitPos.x << " " << a_HitPos.y << " " << a_HitPos.z << std::endl; - m_IsInGround = true; BroadcastMovementUpdate(); -- cgit v1.2.3 From e40c5a20c8efd03fdb3146eb7ec48e26a5e8c655 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 29 Jan 2014 17:47:32 +0100 Subject: Plugin files are loaded in alphabetical order. Except for the Info.lua file which gets loaded always last. Implements #597. --- src/Bindings/PluginLua.cpp | 52 +++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index 1d8c4c6ed..7b2362887 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -88,36 +88,55 @@ bool cPluginLua::Initialize(void) std::string PluginPath = FILE_IO_PREFIX + GetLocalFolder() + "/"; - // Load all files for this plugin, and execute them + // List all Lua files for this plugin. Info.lua has a special handling - make it the last to load: AStringVector Files = cFile::GetFolderContents(PluginPath.c_str()); - - int numFiles = 0; - for (AStringVector::const_iterator itr = Files.begin(); itr != Files.end(); ++itr) + AStringVector LuaFiles; + bool HasInfoLua = false; + for (AStringVector::const_iterator itr = Files.begin(), end = Files.end(); itr != end; ++itr) { - if (itr->rfind(".lua") == AString::npos) + if (itr->rfind(".lua") != AString::npos) { - continue; + if (*itr == "Info.lua") + { + HasInfoLua = true; + } + else + { + LuaFiles.push_back(*itr); + } } + } + std::sort(LuaFiles.begin(), LuaFiles.end()); + + // Warn if there are no Lua files in the plugin folder: + if (LuaFiles.empty()) + { + LOGWARNING("No lua files found: plugin %s is missing.", GetName().c_str()); + Close(); + return false; + } + + // Load all files in the list, including the Info.lua as last, if it exists: + for (AStringVector::const_iterator itr = LuaFiles.begin(), end = LuaFiles.end(); itr != end; ++itr) + { AString Path = PluginPath + *itr; if (!m_LuaState.LoadFile(Path)) { Close(); return false; - } - else - { - numFiles++; } } // for itr - Files[] - - if (numFiles == 0) + if (HasInfoLua) { - LOGWARNING("No lua files found: plugin %s is missing.", GetName().c_str()); - Close(); - return false; + AString Path = PluginPath + "Info.lua"; + if (!m_LuaState.LoadFile(Path)) + { + Close(); + return false; + } } - // Call intialize function + // Call the Initialize function: bool res = false; if (!m_LuaState.Call("Initialize", this, cLuaState::Return, res)) { @@ -125,7 +144,6 @@ bool cPluginLua::Initialize(void) Close(); return false; } - if (!res) { LOGINFO("Plugin %s: Initialize() call failed, plugin is temporarily disabled.", GetName().c_str()); -- cgit v1.2.3 From 04107fa85d142e31576042cff5677a36e392f9f4 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 29 Jan 2014 17:59:49 +0100 Subject: Limited sign lines to 15 chars. Fixes #598. --- src/Protocol/Protocol17x.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 0e9759194..04bade867 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -985,10 +985,11 @@ void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, cons Pkt.WriteInt(a_BlockX); Pkt.WriteShort((short)a_BlockY); Pkt.WriteInt(a_BlockZ); - Pkt.WriteString(a_Line1); - Pkt.WriteString(a_Line2); - Pkt.WriteString(a_Line3); - Pkt.WriteString(a_Line4); + // Need to send only up to 15 chars, otherwise the client crashes (#598) + Pkt.WriteString(a_Line1.substr(0, 15)); + Pkt.WriteString(a_Line2.substr(0, 15)); + Pkt.WriteString(a_Line3.substr(0, 15)); + Pkt.WriteString(a_Line4.substr(0, 15)); } -- cgit v1.2.3 From ebe0f9372fa8787b3fe709937ebd3af30810f910 Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Wed, 29 Jan 2014 18:08:33 +0100 Subject: Now mobs follow you when holding their breed item --- src/Mobs/Chicken.cpp | 25 ++++++++++++++++++++++++- src/Mobs/Chicken.h | 3 +++ src/Mobs/Cow.cpp | 28 ++++++++++++++++++++++++++-- src/Mobs/Cow.h | 8 ++++++++ src/Mobs/Mooshroom.cpp | 27 +++++++++++++++++++++++++++ src/Mobs/Mooshroom.h | 8 ++++++++ src/Mobs/Pig.cpp | 27 ++++++++++++++++++++++++++- src/Mobs/Pig.h | 4 ++++ src/Mobs/Sheep.cpp | 24 ++++++++++++++++++++++++ src/Mobs/Sheep.h | 4 +++- 10 files changed, 153 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Mobs/Chicken.cpp b/src/Mobs/Chicken.cpp index 087fd088a..52c8d3788 100644 --- a/src/Mobs/Chicken.cpp +++ b/src/Mobs/Chicken.cpp @@ -2,7 +2,7 @@ #include "Chicken.h" #include "../World.h" - +#include "../Entities/Player.h" @@ -41,6 +41,29 @@ void cChicken::Tick(float a_Dt, cChunk & a_Chunk) { m_EggDropTimer++; } + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) + { + if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_SEEDS) + { + if (!IsBegging()) + { + m_IsBegging = true; + m_World->BroadcastEntityMetadata(*this); + } + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + PlayerPos.y++; + m_FinalDestination = PlayerPos; + } + else + { + if (IsBegging()) + { + m_IsBegging = false; + m_World->BroadcastEntityMetadata(*this); + } + } + } } diff --git a/src/Mobs/Chicken.h b/src/Mobs/Chicken.h index 979c4d8a0..b9cff40d4 100644 --- a/src/Mobs/Chicken.h +++ b/src/Mobs/Chicken.h @@ -19,10 +19,13 @@ public: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + bool IsBegging (void) const { return m_IsBegging; } + private: int m_EggDropTimer; + bool m_IsBegging; } ; diff --git a/src/Mobs/Cow.cpp b/src/Mobs/Cow.cpp index 9eb74dac2..205ecc73f 100644 --- a/src/Mobs/Cow.cpp +++ b/src/Mobs/Cow.cpp @@ -41,5 +41,29 @@ void cCow::OnRightClicked(cPlayer & a_Player) } } - - +void cCow::Tick(float a_Dt, cChunk & a_Chunk) +{ + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) + { + if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_WHEAT) + { + if (!IsBegging()) + { + m_IsBegging = true; + m_World->BroadcastEntityMetadata(*this); + } + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + PlayerPos.y++; + m_FinalDestination = PlayerPos; + } + else + { + if (IsBegging()) + { + m_IsBegging = false; + m_World->BroadcastEntityMetadata(*this); + } + } + } +} diff --git a/src/Mobs/Cow.h b/src/Mobs/Cow.h index 0391d4a31..b001ea856 100644 --- a/src/Mobs/Cow.h +++ b/src/Mobs/Cow.h @@ -19,6 +19,14 @@ 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 IsBegging (void) const { return m_IsBegging; } + +private: + + bool m_IsBegging; + } ; diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp index 940e2db44..1ff90392d 100644 --- a/src/Mobs/Mooshroom.cpp +++ b/src/Mobs/Mooshroom.cpp @@ -2,6 +2,7 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Mooshroom.h" +#include "../Entities/Player.h" @@ -29,5 +30,31 @@ void cMooshroom::GetDrops(cItems & a_Drops, cEntity * a_Killer) } +void cMooshroom::Tick(float a_Dt, cChunk & a_Chunk) +{ + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) + { + if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_WHEAT) + { + if (!IsBegging()) + { + m_IsBegging = true; + m_World->BroadcastEntityMetadata(*this); + } + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + PlayerPos.y++; + m_FinalDestination = PlayerPos; + } + else + { + if (IsBegging()) + { + m_IsBegging = false; + m_World->BroadcastEntityMetadata(*this); + } + } + } +} diff --git a/src/Mobs/Mooshroom.h b/src/Mobs/Mooshroom.h index 73f6348b6..c288f68a9 100644 --- a/src/Mobs/Mooshroom.h +++ b/src/Mobs/Mooshroom.h @@ -18,6 +18,14 @@ public: CLASS_PROTODEF(cMooshroom); virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + + bool IsBegging (void) const { return m_IsBegging; } + +private: + + bool m_IsBegging; + } ; diff --git a/src/Mobs/Pig.cpp b/src/Mobs/Pig.cpp index 0871a38a9..e31bc90ba 100644 --- a/src/Mobs/Pig.cpp +++ b/src/Mobs/Pig.cpp @@ -71,7 +71,32 @@ void cPig::OnRightClicked(cPlayer & a_Player) } } - +void cPig::Tick(float a_Dt, cChunk & a_Chunk) +{ + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) + { + if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_CARROT) + { + if (!IsBegging()) + { + m_IsBegging = true; + m_World->BroadcastEntityMetadata(*this); + } + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + PlayerPos.y++; + m_FinalDestination = PlayerPos; + } + else + { + if (IsBegging()) + { + m_IsBegging = false; + m_World->BroadcastEntityMetadata(*this); + } + } + } +} diff --git a/src/Mobs/Pig.h b/src/Mobs/Pig.h index 4fd0d8db8..f42a4f412 100644 --- a/src/Mobs/Pig.h +++ b/src/Mobs/Pig.h @@ -19,10 +19,14 @@ 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 IsSaddled(void) const { return m_bIsSaddled; } + bool IsBegging (void) const { return m_IsBegging; } private: + bool m_IsBegging; bool m_bIsSaddled; } ; diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index 702108ae4..3fb9351ad 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -96,4 +96,28 @@ void cSheep::Tick(float a_Dt, cChunk & a_Chunk) } } } + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) + { + if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_WHEAT) + { + if (!IsBegging()) + { + m_IsBegging = true; + m_World->BroadcastEntityMetadata(*this); + } + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + PlayerPos.y++; + m_FinalDestination = PlayerPos; + } + else + { + if (IsBegging()) + { + m_IsBegging = false; + m_World->BroadcastEntityMetadata(*this); + } + } + } } + diff --git a/src/Mobs/Sheep.h b/src/Mobs/Sheep.h index 4eee3db1c..322b31dd9 100644 --- a/src/Mobs/Sheep.h +++ b/src/Mobs/Sheep.h @@ -21,11 +21,13 @@ public: virtual void OnRightClicked(cPlayer & a_Player) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + bool IsBegging(void) const { return m_IsBegging; } bool IsSheared(void) const { return m_IsSheared; } int GetFurColor(void) const { return m_WoolColor; } private: - + + bool m_IsBegging; bool m_IsSheared; int m_WoolColor; int m_TimeToStopEating; -- cgit v1.2.3 From 73d9a285d511a3cd1016aafc8c492924e6a7b249 Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Wed, 29 Jan 2014 18:25:10 +0100 Subject: Fixed a copypasta error... --- src/Mobs/Cow.cpp | 3 ++- src/Mobs/Mooshroom.cpp | 1 + src/Mobs/Pig.cpp | 1 + src/Mobs/Sheep.cpp | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Mobs/Cow.cpp b/src/Mobs/Cow.cpp index 205ecc73f..4063f034d 100644 --- a/src/Mobs/Cow.cpp +++ b/src/Mobs/Cow.cpp @@ -42,7 +42,8 @@ void cCow::OnRightClicked(cPlayer & a_Player) } void cCow::Tick(float a_Dt, cChunk & a_Chunk) -{ +{ + super::Tick(a_Dt, a_Chunk); cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); if (a_Closest_Player != NULL) { diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp index 1ff90392d..60721f0ee 100644 --- a/src/Mobs/Mooshroom.cpp +++ b/src/Mobs/Mooshroom.cpp @@ -32,6 +32,7 @@ void cMooshroom::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cMooshroom::Tick(float a_Dt, cChunk & a_Chunk) { + super::Tick(a_Dt, a_Chunk); cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); if (a_Closest_Player != NULL) { diff --git a/src/Mobs/Pig.cpp b/src/Mobs/Pig.cpp index e31bc90ba..b6d11d856 100644 --- a/src/Mobs/Pig.cpp +++ b/src/Mobs/Pig.cpp @@ -73,6 +73,7 @@ void cPig::OnRightClicked(cPlayer & a_Player) void cPig::Tick(float a_Dt, cChunk & a_Chunk) { + super::Tick(a_Dt, a_Chunk); cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); if (a_Closest_Player != NULL) { diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index 3fb9351ad..2478ec79c 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -68,6 +68,7 @@ void cSheep::OnRightClicked(cPlayer & a_Player) void cSheep::Tick(float a_Dt, cChunk & a_Chunk) { + super::Tick(a_Dt, a_Chunk); // The sheep should not move when he's eating so only handle the physics. if (m_TimeToStopEating > 0) { -- cgit v1.2.3 From ba4865f7ee99490ff46d4b584ffa0ae85fa21aae Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Wed, 29 Jan 2014 18:32:46 +0100 Subject: Fixed sheep --- src/Mobs/Sheep.cpp | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index 2478ec79c..c8ff8f5c8 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -68,7 +68,6 @@ void cSheep::OnRightClicked(cPlayer & a_Player) void cSheep::Tick(float a_Dt, cChunk & a_Chunk) { - super::Tick(a_Dt, a_Chunk); // The sheep should not move when he's eating so only handle the physics. if (m_TimeToStopEating > 0) { @@ -96,27 +95,27 @@ void cSheep::Tick(float a_Dt, cChunk & a_Chunk) m_TimeToStopEating = 40; } } - } - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); - if (a_Closest_Player != NULL) - { - if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_WHEAT) + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) { - if (!IsBegging()) + if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_WHEAT) { - m_IsBegging = true; - m_World->BroadcastEntityMetadata(*this); + if (!IsBegging()) + { + m_IsBegging = true; + m_World->BroadcastEntityMetadata(*this); + } + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + PlayerPos.y++; + m_FinalDestination = PlayerPos; } - Vector3d PlayerPos = a_Closest_Player->GetPosition(); - PlayerPos.y++; - m_FinalDestination = PlayerPos; - } - else - { - if (IsBegging()) + else { - m_IsBegging = false; - m_World->BroadcastEntityMetadata(*this); + if (IsBegging()) + { + m_IsBegging = false; + m_World->BroadcastEntityMetadata(*this); + } } } } -- cgit v1.2.3 From 1c1832b6ce08de71e6a46187420d91eacb18d16e Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Wed, 29 Jan 2014 19:15:26 +0100 Subject: Rewritten code. Implemented xoft suggestion. Using MoveToPosition as tigerw suggested. --- src/Mobs/Chicken.cpp | 23 ----------------------- src/Mobs/Chicken.h | 4 +--- src/Mobs/Cow.cpp | 27 --------------------------- src/Mobs/Cow.h | 7 +------ src/Mobs/Mooshroom.cpp | 28 ---------------------------- src/Mobs/Mooshroom.h | 8 +------- src/Mobs/PassiveMonster.cpp | 16 +++++++++++++++- src/Mobs/PassiveMonster.h | 2 ++ src/Mobs/Pig.cpp | 28 ---------------------------- src/Mobs/Pig.h | 5 ++--- src/Mobs/Sheep.cpp | 23 ----------------------- src/Mobs/Sheep.h | 6 +++--- 12 files changed, 25 insertions(+), 152 deletions(-) (limited to 'src') diff --git a/src/Mobs/Chicken.cpp b/src/Mobs/Chicken.cpp index 52c8d3788..90d56d1de 100644 --- a/src/Mobs/Chicken.cpp +++ b/src/Mobs/Chicken.cpp @@ -41,29 +41,6 @@ void cChicken::Tick(float a_Dt, cChunk & a_Chunk) { m_EggDropTimer++; } - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); - if (a_Closest_Player != NULL) - { - if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_SEEDS) - { - if (!IsBegging()) - { - m_IsBegging = true; - m_World->BroadcastEntityMetadata(*this); - } - Vector3d PlayerPos = a_Closest_Player->GetPosition(); - PlayerPos.y++; - m_FinalDestination = PlayerPos; - } - else - { - if (IsBegging()) - { - m_IsBegging = false; - m_World->BroadcastEntityMetadata(*this); - } - } - } } diff --git a/src/Mobs/Chicken.h b/src/Mobs/Chicken.h index b9cff40d4..a4c1d6b9e 100644 --- a/src/Mobs/Chicken.h +++ b/src/Mobs/Chicken.h @@ -19,13 +19,11 @@ public: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - bool IsBegging (void) const { return m_IsBegging; } + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_SEEDS); } private: - int m_EggDropTimer; - bool m_IsBegging; } ; diff --git a/src/Mobs/Cow.cpp b/src/Mobs/Cow.cpp index 4063f034d..d8e905217 100644 --- a/src/Mobs/Cow.cpp +++ b/src/Mobs/Cow.cpp @@ -41,30 +41,3 @@ void cCow::OnRightClicked(cPlayer & a_Player) } } -void cCow::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); - if (a_Closest_Player != NULL) - { - if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_WHEAT) - { - if (!IsBegging()) - { - m_IsBegging = true; - m_World->BroadcastEntityMetadata(*this); - } - Vector3d PlayerPos = a_Closest_Player->GetPosition(); - PlayerPos.y++; - m_FinalDestination = PlayerPos; - } - else - { - if (IsBegging()) - { - m_IsBegging = false; - m_World->BroadcastEntityMetadata(*this); - } - } - } -} diff --git a/src/Mobs/Cow.h b/src/Mobs/Cow.h index b001ea856..973171ab5 100644 --- a/src/Mobs/Cow.h +++ b/src/Mobs/Cow.h @@ -19,13 +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 IsBegging (void) const { return m_IsBegging; } - -private: - - bool m_IsBegging; + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } } ; diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp index 60721f0ee..00ba339a6 100644 --- a/src/Mobs/Mooshroom.cpp +++ b/src/Mobs/Mooshroom.cpp @@ -30,32 +30,4 @@ void cMooshroom::GetDrops(cItems & a_Drops, cEntity * a_Killer) } -void cMooshroom::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); - if (a_Closest_Player != NULL) - { - if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_WHEAT) - { - if (!IsBegging()) - { - m_IsBegging = true; - m_World->BroadcastEntityMetadata(*this); - } - Vector3d PlayerPos = a_Closest_Player->GetPosition(); - PlayerPos.y++; - m_FinalDestination = PlayerPos; - } - else - { - if (IsBegging()) - { - m_IsBegging = false; - m_World->BroadcastEntityMetadata(*this); - } - } - } -} - diff --git a/src/Mobs/Mooshroom.h b/src/Mobs/Mooshroom.h index c288f68a9..c94301098 100644 --- a/src/Mobs/Mooshroom.h +++ b/src/Mobs/Mooshroom.h @@ -18,14 +18,8 @@ public: CLASS_PROTODEF(cMooshroom); virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - - bool IsBegging (void) const { return m_IsBegging; } - -private: - - bool m_IsBegging; + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } } ; diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp index d774d3170..903761a95 100644 --- a/src/Mobs/PassiveMonster.cpp +++ b/src/Mobs/PassiveMonster.cpp @@ -3,7 +3,7 @@ #include "PassiveMonster.h" #include "../World.h" - +#include "../Entities/Player.h" @@ -39,6 +39,20 @@ void cPassiveMonster::Tick(float a_Dt, cChunk & a_Chunk) { CheckEventLostPlayer(); } + cItem FollowedItem = GetFollowedItem(); + if (FollowedItem.IsEmpty()) + { + return; + } + cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + if (a_Closest_Player != NULL) + { + if (a_Closest_Player->GetEquippedItem().m_ItemType == FollowedItem.m_ItemType) + { + Vector3d PlayerPos = a_Closest_Player->GetPosition(); + MoveToPosition(PlayerPos); + } + } } diff --git a/src/Mobs/PassiveMonster.h b/src/Mobs/PassiveMonster.h index 14a6be6b1..7da5d71bc 100644 --- a/src/Mobs/PassiveMonster.h +++ b/src/Mobs/PassiveMonster.h @@ -20,6 +20,8 @@ public: /// When hit by someone, run away virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; + virtual const cItem GetFollowedItem(void) const { return cItem(); } + } ; diff --git a/src/Mobs/Pig.cpp b/src/Mobs/Pig.cpp index b6d11d856..d8f3dda37 100644 --- a/src/Mobs/Pig.cpp +++ b/src/Mobs/Pig.cpp @@ -71,33 +71,5 @@ void cPig::OnRightClicked(cPlayer & a_Player) } } -void cPig::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); - if (a_Closest_Player != NULL) - { - if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_CARROT) - { - if (!IsBegging()) - { - m_IsBegging = true; - m_World->BroadcastEntityMetadata(*this); - } - Vector3d PlayerPos = a_Closest_Player->GetPosition(); - PlayerPos.y++; - m_FinalDestination = PlayerPos; - } - else - { - if (IsBegging()) - { - m_IsBegging = false; - m_World->BroadcastEntityMetadata(*this); - } - } - } -} - diff --git a/src/Mobs/Pig.h b/src/Mobs/Pig.h index f42a4f412..d434324c1 100644 --- a/src/Mobs/Pig.h +++ b/src/Mobs/Pig.h @@ -19,14 +19,13 @@ 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; + + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_CARROT); } bool IsSaddled(void) const { return m_bIsSaddled; } - bool IsBegging (void) const { return m_IsBegging; } private: - bool m_IsBegging; bool m_bIsSaddled; } ; diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index c8ff8f5c8..4761103e5 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -95,29 +95,6 @@ void cSheep::Tick(float a_Dt, cChunk & a_Chunk) m_TimeToStopEating = 40; } } - cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); - if (a_Closest_Player != NULL) - { - if (a_Closest_Player->GetEquippedItem().m_ItemType == E_ITEM_WHEAT) - { - if (!IsBegging()) - { - m_IsBegging = true; - m_World->BroadcastEntityMetadata(*this); - } - Vector3d PlayerPos = a_Closest_Player->GetPosition(); - PlayerPos.y++; - m_FinalDestination = PlayerPos; - } - else - { - if (IsBegging()) - { - m_IsBegging = false; - m_World->BroadcastEntityMetadata(*this); - } - } - } } } diff --git a/src/Mobs/Sheep.h b/src/Mobs/Sheep.h index 322b31dd9..402e8e61c 100644 --- a/src/Mobs/Sheep.h +++ b/src/Mobs/Sheep.h @@ -21,13 +21,13 @@ public: virtual void OnRightClicked(cPlayer & a_Player) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; - bool IsBegging(void) const { return m_IsBegging; } + virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); } + bool IsSheared(void) const { return m_IsSheared; } int GetFurColor(void) const { return m_WoolColor; } private: - - bool m_IsBegging; + bool m_IsSheared; int m_WoolColor; int m_TimeToStopEating; -- cgit v1.2.3 From e9c1d1ea9c79d9a57d48b625d9a31604e927609c Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Wed, 29 Jan 2014 20:02:41 +0100 Subject: Did what xoft said --- src/Mobs/Chicken.cpp | 1 - src/Mobs/Mooshroom.cpp | 2 -- src/Mobs/PassiveMonster.cpp | 2 +- src/Mobs/PassiveMonster.h | 3 ++- 4 files changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Mobs/Chicken.cpp b/src/Mobs/Chicken.cpp index 90d56d1de..fab92ce49 100644 --- a/src/Mobs/Chicken.cpp +++ b/src/Mobs/Chicken.cpp @@ -2,7 +2,6 @@ #include "Chicken.h" #include "../World.h" -#include "../Entities/Player.h" diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp index 00ba339a6..88101cd83 100644 --- a/src/Mobs/Mooshroom.cpp +++ b/src/Mobs/Mooshroom.cpp @@ -2,8 +2,6 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Mooshroom.h" -#include "../Entities/Player.h" - diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp index 903761a95..904cd63cc 100644 --- a/src/Mobs/PassiveMonster.cpp +++ b/src/Mobs/PassiveMonster.cpp @@ -47,7 +47,7 @@ void cPassiveMonster::Tick(float a_Dt, cChunk & a_Chunk) cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); if (a_Closest_Player != NULL) { - if (a_Closest_Player->GetEquippedItem().m_ItemType == FollowedItem.m_ItemType) + if (a_Closest_Player->GetEquippedItem().IsEqual(FollowedItem)) { Vector3d PlayerPos = a_Closest_Player->GetPosition(); MoveToPosition(PlayerPos); diff --git a/src/Mobs/PassiveMonster.h b/src/Mobs/PassiveMonster.h index 7da5d71bc..0b3c155da 100644 --- a/src/Mobs/PassiveMonster.h +++ b/src/Mobs/PassiveMonster.h @@ -19,7 +19,8 @@ public: /// When hit by someone, run away virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; - + /** Returns the item that the animal of this class follows when a player holds it in hand + Return an empty item not to follow (default). */ virtual const cItem GetFollowedItem(void) const { return cItem(); } } ; -- cgit v1.2.3 From b61a74d6a20f063e776bb02e471a213da32c1000 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 29 Jan 2014 22:56:23 +0100 Subject: Lua: Fixed an error in table-functions callbacks. --- src/Bindings/LuaState.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index 2fca7142c..d49cd8ef3 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -289,9 +289,13 @@ bool cLuaState::PushFunction(const cTableRef & a_TableRef) if (lua_isnil(m_LuaState, -1) || !lua_isfunction(m_LuaState, -1)) { // Not a valid function, bail out - lua_pop(m_LuaState, 2); + lua_pop(m_LuaState, 3); return false; } + + // Pop the table off the stack: + lua_remove(m_LuaState, -2); + Printf(m_CurrentFunctionName, "", a_TableRef.GetFnName()); m_NumCurrentFunctionArgs = 0; return true; -- cgit v1.2.3 From 16a939a75763569352ffdc685b38f41ddd278ff1 Mon Sep 17 00:00:00 2001 From: tonibm19 Date: Thu, 30 Jan 2014 18:02:37 +0100 Subject: Attempt at implementing #563 Not tested (I don't have RasPi) --- src/World.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/World.cpp b/src/World.cpp index 88bbf5f8a..5739098e4 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1,4 +1,3 @@ - #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "BlockID.h" @@ -234,7 +233,7 @@ cWorld::cWorld(const AString & a_WorldName) : m_WorldName(a_WorldName), m_IniFileName(m_WorldName + "/world.ini"), m_StorageSchema("Default"), -#ifdef _arm_ +#ifdef __arm__ m_StorageCompressionFactor(0), #else m_StorageCompressionFactor(6), -- cgit v1.2.3 From 419778a3067fda111c7b3e02b062afc592abb605 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Thu, 30 Jan 2014 21:39:31 +0100 Subject: Fixes #606 --- src/WorldStorage/NBTChunkSerializer.cpp | 4 ++-- src/WorldStorage/WSSAnvil.cpp | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index e46a28caa..9c454c028 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -454,8 +454,8 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) } case cMonster::mtWolf: { - // TODO: - // _X: CopyPasta error: m_Writer.AddInt("Profession", ((const cVillager *)a_Monster)->GetVilType()); + m_Writer.AddString("Owner", ((const cWolf *)a_Monster)->GetOwner()); + m_Writer.AddByte("Sitting", ((const cWolf *)a_Monster)->IsSitting()); break; } case cMonster::mtZombie: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index a0f9136d8..ab85cf3e2 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1876,6 +1876,13 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N { return; } + int OwnerIdx = a_NBT.FindChildByName(a_TagIdx, "Owner"); + AString OwnerName = a_NBT.GetString(OwnerIdx); + if (OwnerName != "") + { + Monster->SetOwner(OwnerName); + Monster->SetIsTame(true); + } a_Entities.push_back(Monster.release()); } -- cgit v1.2.3 From 1a361be44fe2a454734e3ac0e93211e33e566976 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Thu, 30 Jan 2014 21:46:45 +0100 Subject: Check if the tag is found. --- src/WorldStorage/WSSAnvil.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index ab85cf3e2..1827eff58 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1877,6 +1877,11 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N return; } int OwnerIdx = a_NBT.FindChildByName(a_TagIdx, "Owner"); + if (TypeIdx < 0) + { + return; + } + AString OwnerName = a_NBT.GetString(OwnerIdx); if (OwnerName != "") { -- cgit v1.2.3 From 550a09020d4e40904a205ebe7daf1d2421e51070 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Thu, 30 Jan 2014 21:49:39 +0100 Subject: Fixed bad variable. --- src/WorldStorage/WSSAnvil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 1827eff58..e581c433e 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1877,7 +1877,7 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N return; } int OwnerIdx = a_NBT.FindChildByName(a_TagIdx, "Owner"); - if (TypeIdx < 0) + if (OwnerIdx < 0) { return; } -- cgit v1.2.3 From 66427d754b66c91ce76ca23cdbf6bf9c1b377d23 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 30 Jan 2014 17:41:57 +0100 Subject: Added cChunkDest::UpdateHeightmap() This function is necessary for plugins manipulating the generated chunks, they need to update the heightmap before it is passed back to the generator. --- src/Generating/ChunkDesc.cpp | 25 +++++++++++++++++++++++++ src/Generating/ChunkDesc.h | 40 +++++++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp index af1a8a6c7..87566aa78 100644 --- a/src/Generating/ChunkDesc.cpp +++ b/src/Generating/ChunkDesc.cpp @@ -562,6 +562,31 @@ cBlockEntity * cChunkDesc::GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ) +void cChunkDesc::UpdateHeightmap(void) +{ + for (int x = 0; x < cChunkDef::Width; x++) + { + for (int z = 0; z < cChunkDef::Width; z++) + { + int Height = 0; + for (int y = cChunkDef::Height - 1; y > 0; y--) + { + BLOCKTYPE BlockType = GetBlockType(x, y, z); + if (BlockType != E_BLOCK_AIR) + { + Height = y; + break; + } + } // for y + SetHeight(x, z, Height); + } // for z + } // for x +} + + + + + void cChunkDesc::CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas) { const NIBBLETYPE * AreaMetas = m_BlockArea.GetBlockMetas(); diff --git a/src/Generating/ChunkDesc.h b/src/Generating/ChunkDesc.h index e130c463f..e258383d5 100644 --- a/src/Generating/ChunkDesc.h +++ b/src/Generating/ChunkDesc.h @@ -30,7 +30,7 @@ class cChunkDesc public: // tolua_end - /// Uncompressed block metas, 1 meta per byte + /** Uncompressed block metas, 1 meta per byte */ typedef NIBBLETYPE BlockNibbleBytes[cChunkDef::NumBlocks]; cChunkDesc(int a_ChunkX, int a_ChunkZ); @@ -56,6 +56,8 @@ public: void SetBiome(int a_RelX, int a_RelZ, int a_BiomeID); EMCSBiome GetBiome(int a_RelX, int a_RelZ); + // These operate on the heightmap, so they could get out of sync with the data + // Use UpdateHeightmap() to re-sync void SetHeight(int a_RelX, int a_RelZ, int a_Height); int GetHeight(int a_RelX, int a_RelZ); @@ -71,16 +73,16 @@ public: void SetUseDefaultFinish(bool a_bUseDefaultFinish); bool IsUsingDefaultFinish(void) const; - /// Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk. + /** Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk. */ void WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy = cBlockArea::msOverwrite); - /// Reads an area from the chunk into a cBlockArea, blocktypes and blockmetas + /** Reads an area from the chunk into a cBlockArea, blocktypes and blockmetas */ void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ); - /// Returns the maximum height value in the heightmap + /** Returns the maximum height value in the heightmap */ HEIGHTTYPE GetMaxHeight(void) const; - /// Fills the relative cuboid with specified block; allows cuboid out of range of this chunk + /** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */ void FillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, @@ -88,7 +90,7 @@ public: BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ); - /// Fills the relative cuboid with specified block; allows cuboid out of range of this chunk + /** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */ void FillRelCuboid(const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { FillRelCuboid( @@ -99,7 +101,7 @@ public: ); } - /// Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk + /** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */ void ReplaceRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, @@ -108,7 +110,7 @@ public: BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ); - /// Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk + /** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */ void ReplaceRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_SrcType, NIBBLETYPE a_SrcMeta, @@ -124,7 +126,7 @@ public: ); } - /// Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk + /** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */ void FloorRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, @@ -132,7 +134,7 @@ public: BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ); - /// Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk + /** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */ void FloorRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta @@ -146,7 +148,7 @@ public: ); } - /// Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk + /** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */ void RandomFillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, @@ -155,7 +157,7 @@ public: int a_RandomSeed, int a_ChanceOutOf10k ); - /// Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk + /** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */ void RandomFillRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_RandomSeed, int a_ChanceOutOf10k @@ -170,11 +172,15 @@ public: ); } - /// Returns the block entity at the specified coords. - /// If there is no block entity at those coords, tries to create one, based on the block type - /// If the blocktype doesn't support a block entity, returns NULL. + /** Returns the block entity at the specified coords. + If there is no block entity at those coords, tries to create one, based on the block type + If the blocktype doesn't support a block entity, returns NULL. */ cBlockEntity * GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ); + /** Updates the heightmap to match the current contents. + Useful for plugins when writing custom block areas into the chunk */ + void UpdateHeightmap(void); + // tolua_end // Accessors used by cChunkGenerator::Generator descendants: @@ -187,11 +193,11 @@ public: inline cEntityList & GetEntities (void) { return m_Entities; } inline cBlockEntityList & GetBlockEntities (void) { return m_BlockEntities; } - /// Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte) + /** Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte) */ void CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas); #ifdef _DEBUG - /// Verifies that the heightmap corresponds to blocktype contents; if not, asserts on that column + /** Verifies that the heightmap corresponds to blocktype contents; if not, asserts on that column */ void VerifyHeightmap(void); #endif // _DEBUG -- cgit v1.2.3 From 5092ae526629b8eb8e611531a2f312c9177f0673 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 31 Jan 2014 09:19:46 +0100 Subject: Added cPluginManager:BindCommand() form to the API. That's the canonical way to call static functions. --- src/Bindings/ManualBindings.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index e7c66c6fb..ddc93b8c7 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -1429,7 +1429,10 @@ static int tolua_cPluginManager_BindCommand(lua_State * L) // Read the arguments to this API call: tolua_Error tolua_err; int idx = 1; - if (tolua_isusertype(L, 1, "cPluginManager", 0, &tolua_err)) + if ( + tolua_isusertype (L, 1, "cPluginManager", 0, &tolua_err) || + tolua_isusertable(L, 1, "cPluginManager", 0, &tolua_err) + ) { idx++; } -- cgit v1.2.3 From 882d10862202795b8249c1b421fc62bf8bda3892 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 31 Jan 2014 10:20:06 +0100 Subject: Fixed cLineBlockTracer:Trace() signature. --- src/Bindings/ManualBindings.cpp | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index ddc93b8c7..dbaf32756 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -2131,26 +2131,40 @@ protected: static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S) { - // cLineBlockTracer.Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) + /* Supported function signatures: + cLineBlockTracer:Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) // Canonical + cLineBlockTracer.Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) + */ + + // If the first param is the cLineBlockTracer class, shift param index by one: + int idx = 1; + tolua_Error err; + if (tolua_isusertable(tolua_S, 1, "cLineBlockTracer", 0, &err)) + { + idx = 2; + } + + // Check params: cLuaState L(tolua_S); if ( - !L.CheckParamUserType(1, "cWorld") || - !L.CheckParamTable (2) || - !L.CheckParamNumber (3, 8) || - !L.CheckParamEnd (9) + !L.CheckParamUserType(idx, "cWorld") || + !L.CheckParamTable (idx + 1) || + !L.CheckParamNumber (idx + 2, idx + 7) || + !L.CheckParamEnd (idx + 8) ) { return 0; } - cWorld * World = (cWorld *)tolua_tousertype(L, 1, NULL); - cLuaBlockTracerCallbacks Callbacks(L, 2); - double StartX = tolua_tonumber(L, 3, 0); - double StartY = tolua_tonumber(L, 4, 0); - double StartZ = tolua_tonumber(L, 5, 0); - double EndX = tolua_tonumber(L, 6, 0); - double EndY = tolua_tonumber(L, 7, 0); - double EndZ = tolua_tonumber(L, 8, 0); + // Trace: + cWorld * World = (cWorld *)tolua_tousertype(L, idx, NULL); + cLuaBlockTracerCallbacks Callbacks(L, idx + 1); + double StartX = tolua_tonumber(L, idx + 2, 0); + double StartY = tolua_tonumber(L, idx + 3, 0); + double StartZ = tolua_tonumber(L, idx + 4, 0); + double EndX = tolua_tonumber(L, idx + 5, 0); + double EndY = tolua_tonumber(L, idx + 6, 0); + double EndZ = tolua_tonumber(L, idx + 7, 0); bool res = cLineBlockTracer::Trace(*World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ); tolua_pushboolean(L, res ? 1 : 0); return 1; -- cgit v1.2.3 From c7e4ade7c357ce152319bf01527410d8323b929d Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Fri, 31 Jan 2014 16:27:21 +0100 Subject: Wolf: If Owner tag is missing a normal ownerless wolf will spawn. --- src/WorldStorage/WSSAnvil.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index e581c433e..0df97d759 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1879,16 +1879,13 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N int OwnerIdx = a_NBT.FindChildByName(a_TagIdx, "Owner"); if (OwnerIdx < 0) { - return; - } - - AString OwnerName = a_NBT.GetString(OwnerIdx); - if (OwnerName != "") - { - Monster->SetOwner(OwnerName); - Monster->SetIsTame(true); + AString OwnerName = a_NBT.GetString(OwnerIdx); + if (OwnerName != "") + { + Monster->SetOwner(OwnerName); + Monster->SetIsTame(true); + } } - a_Entities.push_back(Monster.release()); } -- cgit v1.2.3 From 19e5122b772dc3183afa204814cec5cd52e5ec1a Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Fri, 31 Jan 2014 16:31:55 +0100 Subject: Inversed condition. --- src/WorldStorage/WSSAnvil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 0df97d759..02396bb16 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1877,7 +1877,7 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N return; } int OwnerIdx = a_NBT.FindChildByName(a_TagIdx, "Owner"); - if (OwnerIdx < 0) + if (OwnerIdx > 0) { AString OwnerName = a_NBT.GetString(OwnerIdx); if (OwnerName != "") -- cgit v1.2.3