summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore61
-rw-r--r--Install/Zip2008_PDBs.list8
-rw-r--r--MCServer/.gitignore1
-rw-r--r--MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua7
m---------MCServer/Plugins/Core0
-rw-r--r--Tools/ProtoProxy/Connection.cpp3
-rw-r--r--src/CMakeLists.txt100
-rw-r--r--src/ClientHandle.cpp14
-rw-r--r--src/Entities/Entity.cpp3
-rw-r--r--src/Entities/Player.cpp93
-rw-r--r--src/Entities/Player.h9
-rw-r--r--src/Items/ItemLighter.h4
-rw-r--r--src/Mobs/Squid.cpp3
-rw-r--r--src/OSSupport/File.cpp9
-rw-r--r--src/OSSupport/File.h45
-rw-r--r--src/Protocol/Protocol17x.cpp83
-rw-r--r--src/Protocol/Protocol17x.h4
-rw-r--r--src/UI/Window.cpp31
-rw-r--r--src/WorldStorage/ScoreboardSerializer.cpp8
-rw-r--r--src/WorldStorage/WSSAnvil.cpp9
-rw-r--r--src/main.cpp21
21 files changed, 333 insertions, 183 deletions
diff --git a/.gitignore b/.gitignore
index a108a9ece..007b21519 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ install_mainfest.txt
src/MCServer
lib/tolua++/tolua
src/Bindings/Bindings.*
+src/Bindings/BindingsDependecies.txt
MCServer.dir/
#win32 cmake stuff
@@ -70,58 +71,8 @@ MCServer.dir/
#cmake output folders
ZERO_CHECK.dir/
-lib/cryptopp/Debug/
-lib/cryptopp/DebugProfile/
-lib/cryptopp/Release/
-lib/cryptopp/ReleaseProfile/
-lib/cryptopp/cryptopp.dir/
-lib/expat/Debug/
-lib/expat/DebugProfile/
-lib/expat/Release/
-lib/expat/ReleaseProfile/
-lib/expat/expat.dir/
-lib/inifile/Debug/
-lib/inifile/DebugProfile/
-lib/inifile/Release/
-lib/inifile/ReleaseProfile/
-lib/inifile/inifile.dir/
-lib/jsoncpp/Debug/
-lib/jsoncpp/DebugProfile/
-lib/jsoncpp/Release/
-lib/jsoncpp/ReleaseProfile/
-lib/jsoncpp/jsoncpp.dir/
-lib/lua/Debug/
-lib/lua/DebugProfile/
-lib/lua/Release/
-lib/lua/ReleaseProfile/
-lib/lua/lua.dir/
-lib/luaexpat/Debug/
-lib/luaexpat/DebugProfile/
-lib/luaexpat/Release/
-lib/luaexpat/ReleaseProfile/
-lib/luaexpat/luaexpat.dir/
-lib/md5/Debug/
-lib/md5/DebugProfile/
-lib/md5/Release/
-lib/md5/ReleaseProfile/
-lib/md5/md5.dir/
-lib/sqlite/Debug/
-lib/sqlite/DebugProfile/
-lib/sqlite/Release/
-lib/sqlite/ReleaseProfile/
-lib/sqlite/sqlite.dir/
-lib/tolua++/Debug/
-lib/tolua++/DebugProfile/
-lib/tolua++/Release/
-lib/tolua++/ReleaseProfile/
-lib/tolua++/tolua.dir/
-lib/tolua++/tolualib.dir/
-lib/zlib/Debug/
-lib/zlib/DebugProfile/
-lib/zlib/Release/
-lib/zlib/ReleaseProfile/
-lib/zlib/zlib.dir/
-src/Debug/
-src/DebugProfile/
-src/Release/
-src/ReleaseProfile/
+Debug/
+DebugProfile/
+Release/
+ReleaseProfile/
+*.dir/
diff --git a/Install/Zip2008_PDBs.list b/Install/Zip2008_PDBs.list
index b9c822c38..608b0185b 100644
--- a/Install/Zip2008_PDBs.list
+++ b/Install/Zip2008_PDBs.list
@@ -1,8 +1,2 @@
MCServer\*.pdb
-VC2008\Release\*.pdb
-VC2008\Release\JsonCpp\*.pdb
-VC2008\Release\Lua\*.pdb
-VC2008\Release\ToLua\*.pdb
-VC2008\Release\webserver\*.pdb
-VC2008\Release\zlib\*.pdb
-src\Bindings.* \ No newline at end of file
+src\Bindings\Bindings.* \ No newline at end of file
diff --git a/MCServer/.gitignore b/MCServer/.gitignore
index c18dd7a67..e3aebbf92 100644
--- a/MCServer/.gitignore
+++ b/MCServer/.gitignore
@@ -4,6 +4,7 @@
*.lib
*.ini
MCServer
+CommLogs/
logs
players
world*
diff --git a/MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua b/MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua
index 85c943721..82d5bb390 100644
--- a/MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua
+++ b/MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua
@@ -5,7 +5,7 @@ return
CalledWhen = "A player is tossing an item. Plugin may override / refuse.",
DefaultFnName = "OnPlayerTossingItem", -- also used as pagename
Desc = [[
- This hook is called when a {{cPlayer|player}} has tossed an item (Q keypress). The
+ This hook is called when a {{cPlayer|player}} has tossed an item. The
{{cPickup|pickup}} has not been spawned yet. Plugins may disallow the tossing, but in that case they
need to clean up - the player's client already thinks the item has been tossed so the
{{cInventory|inventory}} needs to be re-sent to the player.</p>
@@ -18,8 +18,9 @@ return
},
Returns = [[
If the function returns false or no value, other plugins' callbacks are called and finally MCServer
- creates the pickup for the item and tosses it, using {{cPlayer}}:TossItem. If the function returns
- true, no other callbacks are called for this event and MCServer doesn't toss the item.
+ creates the pickup for the item and tosses it, using {{cPlayer}}:TossHeldItem, {{cPlayer}}:TossEquippedItem,
+ or {{cPlayer}}:TossPickup. If the function returns true, no other callbacks are called for this event
+ and MCServer doesn't toss the item.
]],
}, -- HOOK_PLAYER_TOSSING_ITEM
}
diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core
-Subproject 759cf48ba3f1409e6d7b60cb821ee17e589bdef
+Subproject 5fe3662a8719f79cb2ca0a16150c716a3c5eb19
diff --git a/Tools/ProtoProxy/Connection.cpp b/Tools/ProtoProxy/Connection.cpp
index cd66e2dfd..b63935f38 100644
--- a/Tools/ProtoProxy/Connection.cpp
+++ b/Tools/ProtoProxy/Connection.cpp
@@ -243,7 +243,8 @@ void cConnection::Run(void)
FD_ZERO(&ReadFDs);
FD_SET(m_ServerSocket, &ReadFDs);
FD_SET(m_ClientSocket, &ReadFDs);
- int res = select(2, &ReadFDs, NULL, NULL, NULL);
+ SOCKET MaxSocket = std::max(m_ServerSocket, m_ClientSocket);
+ int res = select(MaxSocket + 1, &ReadFDs, NULL, NULL, NULL);
if (res <= 0)
{
printf("select() failed: %d; aborting client", SocketError);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ae8195bc3..944150a44 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -17,34 +17,64 @@ if (NOT MSVC)
#lib dependecies are not included
- set(BINDING_DEPENDECIES ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ChunkDef.h BiomeDef.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} OSSupport/File.h Bindings/LuaFunctions.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginManager.h Bindings/Plugin.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginLua.h Bindings/WebPlugin.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/LuaWindow.h BlockID.h StringUtils.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Defines.h ChatColor.h ClientHandle.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Entity.h Entities/Floater.h )
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Pawn.h Entities/Player.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Pickup.h Entities/ProjectileEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/TNTEntity.h Entities/Effects.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Server.h World.h Inventory.h Enchantments.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Item.h ItemGrid.h BlockEntities/BlockEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/BlockEntityWithItems.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/ChestEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DropSpenserEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DispenserEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DropperEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/FurnaceEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/HopperEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/JukeboxEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/NoteEntity.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/SignEntity.h WebAdmin.h Root.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Vector3f.h Vector3d.h Vector3i.h Matrix4f.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Cuboid.h BoundingBox.h Tracer.h Group.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockArea.h Generating/ChunkDesc.h)
- set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} CraftingRecipes.h UI/Window.h Mobs/Monster.h)
+ set(BINDING_DEPENDECIES
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg
+ ChunkDef.h
+ BiomeDef.h
+ OSSupport/File.h
+ Bindings/LuaFunctions.h
+ Bindings/PluginManager.h
+ Bindings/Plugin.h
+ Bindings/PluginLua.h
+ Bindings/WebPlugin.h
+ Bindings/LuaWindow.h
+ BlockID.h
+ StringUtils.h
+ Defines.h
+ ChatColor.h
+ ClientHandle.h
+ Entities/Entity.h
+ Entities/Floater.h
+ Entities/Pawn.h
+ Entities/Player.h
+ Entities/Pickup.h
+ Entities/ProjectileEntity.h
+ Entities/TNTEntity.h
+ Entities/Effects.h
+ Server.h
+ World.h
+ Inventory.h
+ Enchantments.h
+ Item.h
+ ItemGrid.h
+ BlockEntities/BlockEntity.h
+ BlockEntities/BlockEntityWithItems.h
+ BlockEntities/ChestEntity.h
+ BlockEntities/DropSpenserEntity.h
+ BlockEntities/DispenserEntity.h
+ BlockEntities/DropperEntity.h
+ BlockEntities/FurnaceEntity.h
+ BlockEntities/HopperEntity.h
+ BlockEntities/JukeboxEntity.h
+ BlockEntities/NoteEntity.h
+ BlockEntities/SignEntity.h
+ WebAdmin.h
+ Root.h
+ Vector3f.h
+ Vector3d.h
+ Vector3i.h
+ Matrix4f.h
+ Cuboid.h
+ BoundingBox.h
+ Tracer.h
+ Group.h
+ BlockArea.h
+ Generating/ChunkDesc.h
+ CraftingRecipes.h
+ UI/Window.h
+ Mobs/Monster.h
+ )
include_directories(Bindings)
include_directories(.)
@@ -65,6 +95,13 @@ if (NOT MSVC)
target_link_libraries(Bindings lua sqlite tolualib)
+ #clear file
+ file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt)
+ foreach(dependecy ${BINDING_DEPENDECIES})
+ #write each dependecy on a seperate line
+ file(APPEND ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt "${dependecy}\n")
+ endforeach()
+
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "Bindings.cpp Bindings.h")
foreach(folder ${FOLDERS})
@@ -135,6 +172,13 @@ else ()
"StackWalker.cpp LeakFinder.h" PROPERTIES COMPILE_FLAGS "/Yc\"Globals.h\""
)
list(APPEND SOURCE "Resources/MCServer.rc")
+
+ # Make MSVC generate the PDB files even for the release build:
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi")
+ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
+ set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG")
+ set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /DEBUG")
endif()
set(EXECUTABLE MCServer)
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index ed04edac0..56ad4e4ba 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -148,15 +148,6 @@ cClientHandle::~cClientHandle()
SendDisconnect("Server shut down? Kthnxbai");
}
- // Queue all remaining outgoing packets to cSocketThreads:
- {
- cCSLock Lock(m_CSOutgoingData);
- AString Data;
- m_OutgoingData.ReadAll(Data);
- m_OutgoingData.CommitRead();
- cRoot::Get()->GetServer()->WriteToClient(this, Data);
- }
-
// Close the socket as soon as it sends all outgoing data:
cRoot::Get()->GetServer()->RemoveClient(this);
@@ -657,7 +648,8 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch
// A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return;
}
- m_Player->TossItem(false);
+
+ m_Player->TossEquippedItem();
return;
}
@@ -712,7 +704,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch
// A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return;
}
- m_Player->TossItem(false, 64); // Toss entire slot - if there aren't enough items, the maximum will be ejected
+ m_Player->TossEquippedItem(64); // Toss entire slot - if there aren't enough items, the maximum will be ejected
return;
}
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 565c78dfd..09fb7052d 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -73,7 +73,8 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
cEntity::~cEntity()
{
- ASSERT(!m_World->HasEntity(m_UniqueID)); // Before deleting, the entity needs to have been removed from the world
+ // Before deleting, the entity needs to have been removed from the world, if ever added
+ ASSERT((m_World == NULL) || !m_World->HasEntity(m_UniqueID));
/*
// DEBUG:
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index e5def0156..377194efc 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -1420,59 +1420,68 @@ AString cPlayer::GetColor(void) const
-void cPlayer::TossItem(
- bool a_bDraggingItem,
- char a_Amount /* = 1 */,
- short a_CreateType /* = 0 */,
- short a_CreateHealth /* = 0 */
-)
+void cPlayer::TossEquippedItem(char a_Amount)
{
cItems Drops;
- if (a_CreateType != 0)
+ cItem DroppedItem(GetInventory().GetEquippedItem());
+ if (!DroppedItem.IsEmpty())
{
- // Just create item without touching the inventory (used in creative mode)
- Drops.push_back(cItem(a_CreateType, a_Amount, a_CreateHealth));
+ char NewAmount = a_Amount;
+ if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount)
+ {
+ NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there
+ }
+
+ GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount);
+
+ DroppedItem.m_ItemCount = NewAmount;
+ Drops.push_back(DroppedItem);
}
- else
+
+ double vX = 0, vY = 0, vZ = 0;
+ EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY);
+ vY = -vY * 2 + 1.f;
+ m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player
+}
+
+
+
+
+
+void cPlayer::TossHeldItem(char a_Amount)
+{
+ cItems Drops;
+ cItem & Item = GetDraggingItem();
+ if (!Item.IsEmpty())
{
- // Drop an item from the inventory:
- if (a_bDraggingItem)
+ char OriginalItemAmount = Item.m_ItemCount;
+ Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount);
+ Drops.push_back(Item);
+ if (OriginalItemAmount > a_Amount)
{
- cItem & Item = GetDraggingItem();
- if (!Item.IsEmpty())
- {
- char OriginalItemAmount = Item.m_ItemCount;
- Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount);
- Drops.push_back(Item);
- if (OriginalItemAmount > a_Amount)
- {
- Item.m_ItemCount = OriginalItemAmount - (char)a_Amount;
- }
- else
- {
- Item.Empty();
- }
- }
+ Item.m_ItemCount = OriginalItemAmount - a_Amount;
}
else
{
- // Else drop equipped item
- cItem DroppedItem(GetInventory().GetEquippedItem());
- if (!DroppedItem.IsEmpty())
- {
- char NewAmount = a_Amount;
- if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount)
- {
- NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there
- }
-
- GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount);
-
- DroppedItem.m_ItemCount = NewAmount;
- Drops.push_back(DroppedItem);
- }
+ Item.Empty();
}
}
+
+ double vX = 0, vY = 0, vZ = 0;
+ EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY);
+ vY = -vY * 2 + 1.f;
+ m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player
+}
+
+
+
+
+
+void cPlayer::TossPickup(const cItem & a_Item)
+{
+ cItems Drops;
+ Drops.push_back(a_Item);
+
double vX = 0, vY = 0, vZ = 0;
EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY);
vY = -vY * 2 + 1.f;
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index 52ba2065c..46d0de69d 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -224,7 +224,14 @@ public:
/// Returns the full color code to use for this player, based on their primary group or set in m_Color
AString GetColor(void) const;
- void TossItem(bool a_bDraggingItem, char a_Amount = 1, short a_CreateType = 0, short a_CreateHealth = 0);
+ /** tosses the item in the selected hotbar slot */
+ void TossEquippedItem(char a_Amount = 1);
+
+ /** tosses the item held in hand (when in UI windows) */
+ void TossHeldItem(char a_Amount = 1);
+
+ /** tosses a pickup newly created from a_Item */
+ void TossPickup(const cItem & a_Item);
/// Heals the player by the specified amount of HPs (positive only); sends health update
void Heal(int a_Health);
diff --git a/src/Items/ItemLighter.h b/src/Items/ItemLighter.h
index 4281a2d0c..8f3389d95 100644
--- a/src/Items/ItemLighter.h
+++ b/src/Items/ItemLighter.h
@@ -42,6 +42,10 @@ public:
{
// Light a fire next to/on top of the block if air:
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
+ if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
+ {
+ break;
+ }
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR)
{
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0);
diff --git a/src/Mobs/Squid.cpp b/src/Mobs/Squid.cpp
index a311108ae..5a27762ff 100644
--- a/src/Mobs/Squid.cpp
+++ b/src/Mobs/Squid.cpp
@@ -43,7 +43,8 @@ void cSquid::Tick(float a_Dt, cChunk & a_Chunk)
}
int RelX = (int)floor(Pos.x) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = (int)floor(Pos.z) - a_Chunk.GetPosZ() * cChunkDef::Width;
- if (!IsBlockWater(a_Chunk.GetBlock(RelX, RelY, RelZ)) && !IsOnFire())
+ BLOCKTYPE BlockType;
+ if (a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockType) && !IsBlockWater(BlockType) && !IsOnFire())
{
// Burn for 10 ticks, then decide again
StartBurning(10);
diff --git a/src/OSSupport/File.cpp b/src/OSSupport/File.cpp
index 9f7c0d439..0ebd04915 100644
--- a/src/OSSupport/File.cpp
+++ b/src/OSSupport/File.cpp
@@ -450,3 +450,12 @@ int cFile::Printf(const char * a_Fmt, ...)
+
+void cFile::Flush(void)
+{
+ fflush(m_File);
+}
+
+
+
+
diff --git a/src/OSSupport/File.h b/src/OSSupport/File.h
index 01663a229..07fce6661 100644
--- a/src/OSSupport/File.h
+++ b/src/OSSupport/File.h
@@ -18,6 +18,8 @@ Usage:
2, Check if the file was opened using IsOpen()
3, Read / write
4, Destroy the instance
+
+For reading entire files into memory, just use the static cFile::ReadWholeFile()
*/
@@ -55,7 +57,7 @@ public:
static const char PathSeparator = '/';
#endif
- /// The mode in which to open the file
+ /** The mode in which to open the file */
enum eMode
{
fmRead, // Read-only. If the file doesn't exist, object will not be valid
@@ -63,13 +65,13 @@ public:
fmReadWrite // Read/write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning
} ;
- /// Simple constructor - creates an unopened file object, use Open() to open / create a real file
+ /** Simple constructor - creates an unopened file object, use Open() to open / create a real file */
cFile(void);
- /// Constructs and opens / creates the file specified, use IsOpen() to check for success
+ /** Constructs and opens / creates the file specified, use IsOpen() to check for success */
cFile(const AString & iFileName, eMode iMode);
- /// Auto-closes the file, if open
+ /** Auto-closes the file, if open */
~cFile();
bool Open(const AString & iFileName, eMode iMode);
@@ -77,60 +79,63 @@ public:
bool IsOpen(void) const;
bool IsEOF(void) const;
- /// Reads up to iNumBytes bytes into iBuffer, returns the number of bytes actually read, or -1 on failure; asserts if not open
+ /** Reads up to iNumBytes bytes into iBuffer, returns the number of bytes actually read, or -1 on failure; asserts if not open */
int Read (void * iBuffer, int iNumBytes);
- /// Writes up to iNumBytes bytes from iBuffer, returns the number of bytes actually written, or -1 on failure; asserts if not open
+ /** Writes up to iNumBytes bytes from iBuffer, returns the number of bytes actually written, or -1 on failure; asserts if not open */
int Write(const void * iBuffer, int iNumBytes);
- /// Seeks to iPosition bytes from file start, returns old position or -1 for failure; asserts if not open
+ /** Seeks to iPosition bytes from file start, returns old position or -1 for failure; asserts if not open */
int Seek (int iPosition);
- /// Returns the current position (bytes from file start) or -1 for failure; asserts if not open
+ /** Returns the current position (bytes from file start) or -1 for failure; asserts if not open */
int Tell (void) const;
- /// Returns the size of file, in bytes, or -1 for failure; asserts if not open
+ /** Returns the size of file, in bytes, or -1 for failure; asserts if not open */
int GetSize(void) const;
- /// Reads the file from current position till EOF into an AString; returns the number of bytes read or -1 for error
+ /** Reads the file from current position till EOF into an AString; returns the number of bytes read or -1 for error */
int ReadRestOfFile(AString & a_Contents);
// tolua_begin
- /// Returns true if the file specified exists
+ /** Returns true if the file specified exists */
static bool Exists(const AString & a_FileName);
- /// Deletes a file, returns true if successful
+ /** Deletes a file, returns true if successful */
static bool Delete(const AString & a_FileName);
- /// Renames a file or folder, returns true if successful. May fail if dest already exists (libc-dependant)!
+ /** Renames a file or folder, returns true if successful. May fail if dest already exists (libc-dependant)! */
static bool Rename(const AString & a_OrigPath, const AString & a_NewPath);
- /// Copies a file, returns true if successful.
+ /** Copies a file, returns true if successful. */
static bool Copy(const AString & a_SrcFileName, const AString & a_DstFileName);
- /// Returns true if the specified path is a folder
+ /** Returns true if the specified path is a folder */
static bool IsFolder(const AString & a_Path);
- /// Returns true if the specified path is a regular file
+ /** Returns true if the specified path is a regular file */
static bool IsFile(const AString & a_Path);
- /// Returns the size of the file, or a negative number on error
+ /** Returns the size of the file, or a negative number on error */
static int GetSize(const AString & a_FileName);
- /// Creates a new folder with the specified name. Returns true if successful. Path may be relative or absolute
+ /** Creates a new folder with the specified name. Returns true if successful. Path may be relative or absolute */
static bool CreateFolder(const AString & a_FolderPath);
- /// Returns the entire contents of the specified file as a string. Returns empty string on error.
+ /** Returns the entire contents of the specified file as a string. Returns empty string on error. */
static AString ReadWholeFile(const AString & a_FileName);
// tolua_end
- /// Returns the list of all items in the specified folder (files, folders, nix pipes, whatever's there).
+ /** Returns the list of all items in the specified folder (files, folders, nix pipes, whatever's there). */
static AStringVector GetFolderContents(const AString & a_Folder); // Exported in ManualBindings.cpp
int Printf(const char * a_Fmt, ...);
+ /** Flushes all the bufferef output into the file (only when writing) */
+ void Flush(void);
+
private:
#ifdef USE_STDIO_FILE
FILE * m_File;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index bcc638796..9bb2cfbf0 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -53,6 +53,16 @@ Implements the 1.7.x protocol classes:
+// fwd: main.cpp:
+extern bool g_ShouldLogComm;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cProtocol172:
+
cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
super(a_Client),
m_ServerAddress(a_ServerAddress),
@@ -63,6 +73,13 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd
m_OutPacketLenBuffer(20), // 20 bytes is more than enough for one VarInt
m_IsEncrypted(false)
{
+ // Create the comm log file, if so requested:
+ if (g_ShouldLogComm)
+ {
+ cFile::CreateFolder("CommLogs");
+ AString FileName = Printf("CommLogs/%x__%s.log", (unsigned)time(NULL), a_Client->GetIPString().c_str());
+ m_CommLogFile.Open(FileName, cFile::fmWrite);
+ }
}
@@ -1065,6 +1082,29 @@ 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 (m_ReceivedData.GetReadableSpace() > 0)
+ {
+ AString AllData;
+ int OldReadableSpace = m_ReceivedData.GetReadableSpace();
+ m_ReceivedData.ReadAll(AllData);
+ m_ReceivedData.ResetRead();
+ m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace);
+ AString Hex;
+ CreateHexDump(Hex, AllData.data(), AllData.size(), 16);
+ m_CommLogFile.Printf("Incoming data, %d (0x%x) bytes unparsed already present in buffer:\n%s\n",
+ AllData.size(), AllData.size(), Hex.c_str()
+ );
+ }
+ AString Hex;
+ CreateHexDump(Hex, a_Data, a_Size, 16);
+ m_CommLogFile.Printf("Incoming data: %d (0x%x) bytes: \n%s\n",
+ a_Size, a_Size, Hex.c_str()
+ );
+ }
+
if (!m_ReceivedData.Write(a_Data, a_Size))
{
// Too much data in the incoming queue, report to caller:
@@ -1100,6 +1140,22 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
return;
}
+ // Log the packet info into the comm log file:
+ if (g_ShouldLogComm)
+ {
+ AString PacketData;
+ bb.ReadAll(PacketData);
+ bb.ResetRead();
+ bb.ReadVarInt(PacketType);
+ ASSERT(PacketData.size() > 0);
+ PacketData.resize(PacketData.size() - 1);
+ AString PacketDataHex;
+ CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16);
+ m_CommLogFile.Printf("Next incoming packet is type %u (0x%x), length %u (0x%x) at state %d. Payload:\n%s\n",
+ PacketType, PacketType, PacketLen, PacketLen, m_State, PacketDataHex.c_str()
+ );
+ }
+
if (!HandlePacket(bb, PacketType))
{
// Unknown packet, already been reported, but without the length. Log the length here:
@@ -1116,6 +1172,12 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
LOGD("Packet contents:\n%s", Out.c_str());
#endif // _DEBUG
+ // Put a message in the comm log:
+ if (g_ShouldLogComm)
+ {
+ m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n");
+ }
+
return;
}
@@ -1125,6 +1187,16 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x, state %d. Read %u bytes, packet contained %u bytes",
PacketType, m_State, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen
);
+
+ // Put a message in the comm log:
+ if (g_ShouldLogComm)
+ {
+ m_CommLogFile.Printf("^^^^^^ Wrong number of bytes read for this packet (exp %d left, got %d left) ^^^^^^\n\n\n",
+ 1, bb.GetReadableSpace()
+ );
+ m_CommLogFile.Flush();
+ }
+
ASSERT(!"Read wrong number of bytes!");
m_Client->PacketError(PacketType);
}
@@ -1807,6 +1879,17 @@ cProtocol172::cPacketizer::~cPacketizer()
m_Out.ReadAll(DataToSend);
m_Protocol.SendData(DataToSend.data(), DataToSend.size());
m_Out.CommitRead();
+
+ // Log the comm into logfile:
+ if (g_ShouldLogComm)
+ {
+ AString Hex;
+ ASSERT(DataToSend.size() > 0);
+ CreateHexDump(Hex, DataToSend.data() + 1, DataToSend.size() - 1, 16);
+ m_Protocol.m_CommLogFile.Printf("Outgoing packet: type %d (0x%x), length %u (0x%x), state %d. Payload:\n%s\n",
+ DataToSend[0], DataToSend[0], PacketLen, PacketLen, m_Protocol.m_State, Hex.c_str()
+ );
+ }
}
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 0617b6c00..72544b575 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -222,6 +222,10 @@ protected:
cAESCFBDecryptor m_Decryptor;
cAESCFBEncryptor m_Encryptor;
+
+ /** The logfile where the comm is logged, when g_ShouldLogComm is true */
+ cFile m_CommLogFile;
+
/// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets
void AddReceivedData(const char * a_Data, int a_Size);
diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp
index 3ffeff7a0..1a8456f70 100644
--- a/src/UI/Window.cpp
+++ b/src/UI/Window.cpp
@@ -13,7 +13,8 @@
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/EnderChestEntity.h"
#include "../BlockEntities/HopperEntity.h"
-
+#include "../Root.h"
+#include "../Bindings/PluginManager.h"
@@ -169,6 +170,7 @@ void cWindow::Clicked(
const cItem & a_ClickedItem
)
{
+ cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
if (a_WindowID != m_WindowID)
{
LOGWARNING("%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__, m_WindowID, a_WindowID, a_Player.GetName().c_str());
@@ -179,14 +181,35 @@ void cWindow::Clicked(
{
case caRightClickOutside:
{
+ if (PlgMgr->CallHookPlayerTossingItem(a_Player))
+ {
+ // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
+ return;
+ }
+ if (a_Player.IsGameModeCreative())
+ {
+ a_Player.TossPickup(a_ClickedItem);
+ }
+
// Toss one of the dragged items:
- a_Player.TossItem(true);
+ a_Player.TossHeldItem();
return;
}
case caLeftClickOutside:
{
+ if (PlgMgr->CallHookPlayerTossingItem(a_Player))
+ {
+ // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
+ return;
+ }
+
+ if (a_Player.IsGameModeCreative())
+ {
+ a_Player.TossPickup(a_ClickedItem);
+ }
+
// Toss all dragged items:
- a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount);
+ a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount);
return;
}
case caLeftClickOutsideHoldNothing:
@@ -263,7 +286,7 @@ bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
if (a_Player.IsDraggingItem())
{
LOGD("Player holds item! Dropping it...");
- a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount);
+ a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount);
}
cClientHandle * ClientHandle = a_Player.GetClientHandle();
diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp
index fa094a033..c65e13f98 100644
--- a/src/WorldStorage/ScoreboardSerializer.cpp
+++ b/src/WorldStorage/ScoreboardSerializer.cpp
@@ -31,16 +31,12 @@ cScoreboardSerializer::cScoreboardSerializer(const AString & a_WorldName, cScore
bool cScoreboardSerializer::Load(void)
{
- cFile File;
- if (!File.Open(FILE_IO_PREFIX + m_Path, cFile::fmRead))
+ AString Data = cFile::ReadWholeFile(FILE_IO_PREFIX + m_Path);
+ if (Data.empty())
{
return false;
}
- AString Data;
- File.ReadRestOfFile(Data);
- File.Close();
-
AString Uncompressed;
int res = UncompressStringGZIP(Data.data(), Data.size(), Uncompressed);
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 8be6372e2..e2a882f65 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -1926,14 +1926,19 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N
double Speed[3];
if (!LoadDoublesListFromNBT(Speed, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Motion")))
{
- return false;
+ // Provide default speed:
+ Speed[0] = 0;
+ Speed[1] = 0;
+ Speed[2] = 0;
}
a_Entity.SetSpeed(Speed[0], Speed[1], Speed[2]);
double Rotation[3];
if (!LoadDoublesListFromNBT(Rotation, 2, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Rotation")))
{
- return false;
+ // Provide default rotation:
+ Rotation[0] = 0;
+ Rotation[1] = 0;
}
a_Entity.SetYaw(Rotation[0]);
a_Entity.SetRoll(Rotation[1]);
diff --git a/src/main.cpp b/src/main.cpp
index 340149e0b..06b344c25 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -19,6 +19,13 @@ 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 defined, a thorough leak finder will be used (debug MSVC only); leaks will be output to the Output window
#define ENABLE_LEAK_FINDER
@@ -216,12 +223,24 @@ int main( int argc, char **argv )
#ifndef _DEBUG
std::signal(SIGSEGV, NonCtrlHandler);
std::signal(SIGTERM, NonCtrlHandler);
- std::signal(SIGINT, NonCtrlHandler);
+ std::signal(SIGINT, NonCtrlHandler);
#endif
// DEBUG: test the dumpfile creation:
// *((int *)0) = 0;
+ // Check if comm logging is to be enabled:
+ for (int i = 0; i < argc; i++)
+ {
+ if (
+ (NoCaseCompare(argv[i], "/commlog") == 0) ||
+ (NoCaseCompare(argv[i], "/logcomm") == 0)
+ )
+ {
+ g_ShouldLogComm = true;
+ }
+ }
+
#if !defined(ANDROID_NDK)
try
#endif