summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua2
-rw-r--r--lib/lua/CMakeLists.txt15
-rw-r--r--src/Bindings/ManualBindings.cpp16
-rw-r--r--src/Chunk.cpp17
-rw-r--r--src/Entities/Entity.cpp12
-rw-r--r--src/OSSupport/BlockingTCPLink.cpp11
-rw-r--r--src/OSSupport/Socket.cpp2
-rw-r--r--src/OSSupport/Socket.h12
-rw-r--r--src/Protocol/Protocol17x.cpp40
10 files changed, 105 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore
index c1a868db6..a108a9ece 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
build/
+ipch/
+Win32/
MCServer/MCServer
ChunkWorxSave.ini
doxy/
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index a5b6d8210..f8cb8ed4b 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -2087,7 +2087,7 @@ end
QueueSetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta, TickDelay", Return = "", Notes = "Queues the block to be set to the specified blocktype and meta after the specified amount of game ticks. Uses SetBlock() for the actual setting, so simulators are woken up and block entities are handled correctly." },
QueueTask = { Params = "TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the tick thread. This is the primary means of interaction with a cWorld from the WebAdmin page handlers (see {{WebWorldThreads}}). The function signature is <pre class=\"pretty-print lang-lua\">function()</pre>All return values from the function are ignored. Note that this function is actually called *after* the QueueTask() function returns." },
RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." },
- ScheduleTask = { Params = "TaskFunction, Ticks", Return = "", Notes = "Queues the specified function to be executed in the tick thread after a number of ticks. This enables operations to be queued for execution in the future. The function signature is <pre class=\"pretty-print lang-lua\">function()</pre>All return values from the function are ignored." },
+ ScheduleTask = { Params = "TaskFunction, Ticks", Return = "", Notes = "Queues the specified function to be executed in the world's tick thread after a number of ticks. This enables operations to be queued for execution in the future. The function signature is <pre class=\"pretty-print lang-lua\">function({{cWorld|World}})</pre>All return values from the function are ignored." },
SendBlockTo = { Params = "BlockX, BlockY, BlockZ, {{cPlayer|Player}}", Return = "", Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet." },
SetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances." },
SetBlockMeta =
diff --git a/lib/lua/CMakeLists.txt b/lib/lua/CMakeLists.txt
index 02c20388d..4babae9b2 100644
--- a/lib/lua/CMakeLists.txt
+++ b/lib/lua/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.2)
project (lua)
include_directories ("${PROJECT_SOURCE_DIR}/../../src/")
@@ -25,7 +25,15 @@ if (WIN32)
# Output the executable into the $/MCServer folder, so that MCServer can find it:
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
- SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES
+ SET_TARGET_PROPERTIES(lua PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
+ ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
+ ARCHIVE_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
+ ARCHIVE_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
+ LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
+ LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
+ LIBRARY_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
+ LIBRARY_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
RUNTIME_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
@@ -38,6 +46,9 @@ if (WIN32)
lua PROPERTIES COMPILE_FLAGS "-D_CRT_SECURE_NO_WARNINGS"
)
endif()
+
+ # NOTE: The DLL for each configuration is stored at the same place, thus overwriting each other.
+ # This is known, however such behavior is needed for LuaRocks - they always load "lua.dll"
else()
add_library(lua ${SOURCE})
endif()
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index b12fa5f03..ebee2d697 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -941,6 +941,10 @@ protected:
}
} ;
+
+
+
+
static int tolua_cWorld_QueueTask(lua_State * tolua_S)
{
// Binding for cWorld::QueueTask
@@ -976,6 +980,10 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S)
return 0;
}
+
+
+
+
class cLuaScheduledWorldTask :
public cWorld::cScheduledTask
{
@@ -999,6 +1007,9 @@ protected:
};
+
+
+
static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
{
// Binding for cWorld::ScheduleTask
@@ -1032,12 +1043,14 @@ static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
int Ticks = (int) tolua_tonumber (tolua_S, 3, 0);
- self->ScheduleTask(new cLuaScheduledWorldTask(*Plugin, FnRef,Ticks));
+ self->ScheduleTask(new cLuaScheduledWorldTask(*Plugin, FnRef, Ticks));
return 0;
}
+
+
static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
{
cPluginManager * self = (cPluginManager *)tolua_tousertype(tolua_S, 1, 0);
@@ -2272,6 +2285,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta);
tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines);
tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask);
+ tolua_function(tolua_S, "ScheduleTask", tolua_cWorld_ScheduleTask);
tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines);
tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight);
tolua_function(tolua_S, "UpdateSign", tolua_cWorld_SetSignLines);
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index fb26e983d..0735c8144 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -1743,7 +1743,14 @@ bool cChunk::AddClient(cClientHandle* a_Client)
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
{
- LOGD("cChunk: Entity #%d (%s) at [%i, %i, %i] spawning for player \"%s\"", (*itr)->GetUniqueID(), (*itr)->GetClass(), m_PosX, m_PosY, m_PosZ, a_Client->GetUsername().c_str());
+ /*
+ // DEBUG:
+ LOGD("cChunk: Entity #%d (%s) at [%i, %i, %i] spawning for player \"%s\"",
+ (*itr)->GetUniqueID(), (*itr)->GetClass(),
+ m_PosX, m_PosY, m_PosZ,
+ a_Client->GetUsername().c_str()
+ );
+ */
(*itr)->SpawnOn(*a_Client);
}
return true;
@@ -1768,7 +1775,13 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
{
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
{
- LOGD("chunk [%i, %i] destroying entity #%i for player \"%s\"", m_PosX, m_PosZ, (*itr)->GetUniqueID(), a_Client->GetUsername().c_str() );
+ /*
+ // DEBUG:
+ LOGD("chunk [%i, %i] destroying entity #%i for player \"%s\"",
+ m_PosX, m_PosZ,
+ (*itr)->GetUniqueID(), a_Client->GetUsername().c_str()
+ );
+ */
a_Client->SendDestroyEntity(*(*itr));
}
}
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index e1efe3ccd..565c78dfd 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -75,13 +75,16 @@ cEntity::~cEntity()
{
ASSERT(!m_World->HasEntity(m_UniqueID)); // Before deleting, the entity needs to have been removed from the world
+ /*
+ // DEBUG:
LOGD("Deleting entity %d at pos {%.2f, %.2f, %.2f} ~ [%d, %d]; ptr %p",
m_UniqueID,
m_Pos.x, m_Pos.y, m_Pos.z,
(int)(m_Pos.x / cChunkDef::Width), (int)(m_Pos.z / cChunkDef::Width),
this
);
-
+ */
+
if (m_AttachedTo != NULL)
{
Detach();
@@ -138,9 +141,13 @@ bool cEntity::Initialize(cWorld * a_World)
return false;
}
+ /*
+ // DEBUG:
LOGD("Initializing entity #%d (%s) at {%.02f, %.02f, %.02f}",
m_UniqueID, GetClass(), m_Pos.x, m_Pos.y, m_Pos.z
);
+ */
+
m_IsInitialized = true;
m_World = a_World;
m_World->AddEntity(this);
@@ -617,9 +624,12 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
m_bOnGround = true;
+ /*
+ // DEBUG:
LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
);
+ */
}
if (!m_bOnGround)
diff --git a/src/OSSupport/BlockingTCPLink.cpp b/src/OSSupport/BlockingTCPLink.cpp
index 55454a4b5..08aec0c65 100644
--- a/src/OSSupport/BlockingTCPLink.cpp
+++ b/src/OSSupport/BlockingTCPLink.cpp
@@ -7,17 +7,6 @@
-#ifdef _WIN32
- #define MSG_NOSIGNAL (0)
-#endif
-#ifdef __MACH__
- #define MSG_NOSIGNAL (0)
-#endif
-
-
-
-
-
cBlockingTCPLink::cBlockingTCPLink(void)
{
}
diff --git a/src/OSSupport/Socket.cpp b/src/OSSupport/Socket.cpp
index d511e5487..8ea5d8320 100644
--- a/src/OSSupport/Socket.cpp
+++ b/src/OSSupport/Socket.cpp
@@ -364,7 +364,7 @@ int cSocket::Receive(char* a_Buffer, unsigned int a_Length, unsigned int a_Flags
int cSocket::Send(const char * a_Buffer, unsigned int a_Length)
{
- return send(m_Socket, a_Buffer, a_Length, 0);
+ return send(m_Socket, a_Buffer, a_Length, MSG_NOSIGNAL);
}
diff --git a/src/OSSupport/Socket.h b/src/OSSupport/Socket.h
index 81bfd28fc..b86560de8 100644
--- a/src/OSSupport/Socket.h
+++ b/src/OSSupport/Socket.h
@@ -5,6 +5,18 @@
+// Windows and MacOSX don't have the MSG_NOSIGNAL flag
+#if ( \
+ defined(_WIN32) || \
+ (defined(__APPLE__) && defined(__MACH__)) \
+)
+ #define MSG_NOSIGNAL (0)
+#endif
+
+
+
+
+
class cSocket
{
public:
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 274e59f63..354b2476a 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -121,7 +121,7 @@ void cProtocol172::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, cha
void cProtocol172::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage)
{
- cPacketizer Pkt(*this, 0x24); // Block Break Animation packet
+ cPacketizer Pkt(*this, 0x25); // Block Break Animation packet
Pkt.WriteInt(a_EntityID);
Pkt.WriteInt(a_BlockX);
Pkt.WriteInt(a_BlockY);
@@ -1039,15 +1039,28 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
if (!HandlePacket(bb, PacketType))
{
- // Unknown packet, already been reported, just bail out
+ // Unknown packet, already been reported, but without the length. Log the length here:
+ LOGWARNING("Unhandled packet: type 0x%x, state %d, length %u", PacketType, m_State, PacketLen);
+
+ #ifdef _DEBUG
+ // Dump the packet contents into the log:
+ bb.ResetRead();
+ AString Packet;
+ bb.ReadAll(Packet);
+ Packet.resize(Packet.size() - 1); // Drop the final NUL pushed there for over-read detection
+ AString Out;
+ CreateHexDump(Out, Packet.data(), (int)Packet.size(), 24);
+ LOGD("Packet contents:\n%s", Out.c_str());
+ #endif // _DEBUG
+
return;
}
if (bb.GetReadableSpace() != 1)
{
// Read more or less than packet length, report as error
- LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x. Read %u bytes, packet contained %u bytes",
- PacketType, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen
+ LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x, state %d. Read %u bytes, packet contained %u bytes",
+ PacketType, m_State, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen
);
ASSERT(!"Read wrong number of bytes!");
m_Client->PacketError(PacketType);
@@ -1115,9 +1128,26 @@ bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
}
break;
}
+ default:
+ {
+ // Received a packet in an unknown state, report:
+ LOGWARNING("Received a packet in an unknown protocol state %d. Ignoring further packets.", m_State);
+
+ // Cannot kick the client - we don't know this state and thus the packet number for the kick packet
+
+ // Switch to a state when all further packets are silently ignored:
+ m_State = 255;
+ return false;
+ }
+ case 255:
+ {
+ // This is the state used for "not processing packets anymore" when we receive a bad packet from a client.
+ // Do not output anything (the caller will do that for us), just return failure
+ return false;
+ }
} // switch (m_State)
- // Unknown packet type, report to the client:
+ // Unknown packet type, report to the ClientHandle:
m_Client->PacketUnknown(a_PacketType);
return false;
}