1
0

Merged branch 'master' into ChangeToPolarSSL.

This commit is contained in:
madmaxoft 2014-01-25 15:37:00 +01:00
commit a2dfb28537
21 changed files with 336 additions and 186 deletions

61
.gitignore vendored
View File

@ -57,6 +57,7 @@ install_mainfest.txt
src/MCServer src/MCServer
lib/tolua++/tolua lib/tolua++/tolua
src/Bindings/Bindings.* src/Bindings/Bindings.*
src/Bindings/BindingsDependecies.txt
MCServer.dir/ MCServer.dir/
#win32 cmake stuff #win32 cmake stuff
@ -70,58 +71,8 @@ MCServer.dir/
#cmake output folders #cmake output folders
ZERO_CHECK.dir/ ZERO_CHECK.dir/
lib/cryptopp/Debug/ Debug/
lib/cryptopp/DebugProfile/ DebugProfile/
lib/cryptopp/Release/ Release/
lib/cryptopp/ReleaseProfile/ ReleaseProfile/
lib/cryptopp/cryptopp.dir/ *.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/

View File

@ -1,8 +1,2 @@
MCServer\*.pdb MCServer\*.pdb
VC2008\Release\*.pdb src\Bindings\Bindings.*
VC2008\Release\JsonCpp\*.pdb
VC2008\Release\Lua\*.pdb
VC2008\Release\ToLua\*.pdb
VC2008\Release\webserver\*.pdb
VC2008\Release\zlib\*.pdb
src\Bindings.*

1
MCServer/.gitignore vendored
View File

@ -4,6 +4,7 @@
*.lib *.lib
*.ini *.ini
MCServer MCServer
CommLogs/
logs logs
players players
world* world*

View File

@ -5,7 +5,7 @@ return
CalledWhen = "A player is tossing an item. Plugin may override / refuse.", CalledWhen = "A player is tossing an item. Plugin may override / refuse.",
DefaultFnName = "OnPlayerTossingItem", -- also used as pagename DefaultFnName = "OnPlayerTossingItem", -- also used as pagename
Desc = [[ 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 {{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 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> {{cInventory|inventory}} needs to be re-sent to the player.</p>
@ -18,8 +18,9 @@ return
}, },
Returns = [[ Returns = [[
If the function returns false or no value, other plugins' callbacks are called and finally MCServer 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 creates the pickup for the item and tosses it, using {{cPlayer}}:TossHeldItem, {{cPlayer}}:TossEquippedItem,
true, no other callbacks are called for this event and MCServer doesn't toss the item. 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 }, -- HOOK_PLAYER_TOSSING_ITEM
} }

@ -1 +1 @@
Subproject commit 759cf48ba3f1409e6d7b60cb821ee17e589bdef8 Subproject commit 5fe3662a8719f79cb2ca0a16150c716a3c5eb19c

View File

@ -243,7 +243,8 @@ void cConnection::Run(void)
FD_ZERO(&ReadFDs); FD_ZERO(&ReadFDs);
FD_SET(m_ServerSocket, &ReadFDs); FD_SET(m_ServerSocket, &ReadFDs);
FD_SET(m_ClientSocket, &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) if (res <= 0)
{ {
printf("select() failed: %d; aborting client", SocketError); printf("select() failed: %d; aborting client", SocketError);

View File

@ -17,34 +17,64 @@ if (NOT MSVC)
#lib dependecies are not included #lib dependecies are not included
set(BINDING_DEPENDECIES ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua) set(BINDING_DEPENDECIES
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg) ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} ChunkDef.h BiomeDef.h) ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} OSSupport/File.h Bindings/LuaFunctions.h) ChunkDef.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginManager.h Bindings/Plugin.h) BiomeDef.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/PluginLua.h Bindings/WebPlugin.h) OSSupport/File.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Bindings/LuaWindow.h BlockID.h StringUtils.h) Bindings/LuaFunctions.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Defines.h ChatColor.h ClientHandle.h) Bindings/PluginManager.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Entity.h Entities/Floater.h ) Bindings/Plugin.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Pawn.h Entities/Player.h) Bindings/PluginLua.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/Pickup.h Entities/ProjectileEntity.h) Bindings/WebPlugin.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Entities/TNTEntity.h Entities/Effects.h) Bindings/LuaWindow.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Server.h World.h Inventory.h Enchantments.h) BlockID.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Item.h ItemGrid.h BlockEntities/BlockEntity.h) StringUtils.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/BlockEntityWithItems.h) Defines.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/ChestEntity.h) ChatColor.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DropSpenserEntity.h) ClientHandle.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DispenserEntity.h) Entities/Entity.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/DropperEntity.h) Entities/Floater.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/FurnaceEntity.h) Entities/Pawn.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/HopperEntity.h) Entities/Player.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/JukeboxEntity.h) Entities/Pickup.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/NoteEntity.h) Entities/ProjectileEntity.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockEntities/SignEntity.h WebAdmin.h Root.h) Entities/TNTEntity.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Vector3f.h Vector3d.h Vector3i.h Matrix4f.h) Entities/Effects.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} Cuboid.h BoundingBox.h Tracer.h Group.h) Server.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} BlockArea.h Generating/ChunkDesc.h) World.h
set(BINDING_DEPENDECIES ${BINDING_DEPENDECIES} CraftingRecipes.h UI/Window.h Mobs/Monster.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(Bindings)
include_directories(.) include_directories(.)
@ -65,6 +95,13 @@ if (NOT MSVC)
target_link_libraries(Bindings lua sqlite tolualib) 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") set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "Bindings.cpp Bindings.h")
foreach(folder ${FOLDERS}) foreach(folder ${FOLDERS})
@ -135,6 +172,13 @@ else ()
"StackWalker.cpp LeakFinder.h" PROPERTIES COMPILE_FLAGS "/Yc\"Globals.h\"" "StackWalker.cpp LeakFinder.h" PROPERTIES COMPILE_FLAGS "/Yc\"Globals.h\""
) )
list(APPEND SOURCE "Resources/MCServer.rc") 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() endif()
set(EXECUTABLE MCServer) set(EXECUTABLE MCServer)

View File

@ -148,15 +148,6 @@ cClientHandle::~cClientHandle()
SendDisconnect("Server shut down? Kthnxbai"); 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: // Close the socket as soon as it sends all outgoing data:
cRoot::Get()->GetServer()->RemoveClient(this); 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) // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return; return;
} }
m_Player->TossItem(false);
m_Player->TossEquippedItem();
return; 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) // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return; 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; return;
} }

View File

@ -73,7 +73,8 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
cEntity::~cEntity() 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: // DEBUG:

View File

@ -1420,59 +1420,68 @@ AString cPlayer::GetColor(void) const
void cPlayer::TossItem( void cPlayer::TossEquippedItem(char a_Amount)
bool a_bDraggingItem,
char a_Amount /* = 1 */,
short a_CreateType /* = 0 */,
short a_CreateHealth /* = 0 */
)
{ {
cItems Drops; cItems Drops;
if (a_CreateType != 0) cItem DroppedItem(GetInventory().GetEquippedItem());
if (!DroppedItem.IsEmpty())
{ {
// Just create item without touching the inventory (used in creative mode) char NewAmount = a_Amount;
Drops.push_back(cItem(a_CreateType, a_Amount, a_CreateHealth)); if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount)
}
else
{
// Drop an item from the inventory:
if (a_bDraggingItem)
{ {
cItem & Item = GetDraggingItem(); NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there
if (!Item.IsEmpty()) }
{
char OriginalItemAmount = Item.m_ItemCount; GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount);
Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount);
Drops.push_back(Item); DroppedItem.m_ItemCount = NewAmount;
if (OriginalItemAmount > a_Amount) Drops.push_back(DroppedItem);
{ }
Item.m_ItemCount = OriginalItemAmount - (char)a_Amount;
} double vX = 0, vY = 0, vZ = 0;
else EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY);
{ vY = -vY * 2 + 1.f;
Item.Empty(); m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player
} }
}
void cPlayer::TossHeldItem(char a_Amount)
{
cItems Drops;
cItem & Item = GetDraggingItem();
if (!Item.IsEmpty())
{
char OriginalItemAmount = Item.m_ItemCount;
Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount);
Drops.push_back(Item);
if (OriginalItemAmount > a_Amount)
{
Item.m_ItemCount = OriginalItemAmount - a_Amount;
} }
else else
{ {
// Else drop equipped item Item.Empty();
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);
}
} }
} }
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; double vX = 0, vY = 0, vZ = 0;
EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY);
vY = -vY * 2 + 1.f; vY = -vY * 2 + 1.f;

View File

@ -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 /// Returns the full color code to use for this player, based on their primary group or set in m_Color
AString GetColor(void) const; 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 /// Heals the player by the specified amount of HPs (positive only); sends health update
void Heal(int a_Health); void Heal(int a_Health);

View File

@ -42,6 +42,10 @@ public:
{ {
// Light a fire next to/on top of the block if air: // Light a fire next to/on top of the block if air:
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); 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) 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); a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0);

View File

@ -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 RelX = (int)floor(Pos.x) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = (int)floor(Pos.z) - a_Chunk.GetPosZ() * 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 // Burn for 10 ticks, then decide again
StartBurning(10); StartBurning(10);

View File

@ -450,3 +450,12 @@ int cFile::Printf(const char * a_Fmt, ...)
void cFile::Flush(void)
{
fflush(m_File);
}

View File

@ -18,6 +18,8 @@ Usage:
2, Check if the file was opened using IsOpen() 2, Check if the file was opened using IsOpen()
3, Read / write 3, Read / write
4, Destroy the instance 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 = '/'; static const char PathSeparator = '/';
#endif #endif
/// The mode in which to open the file /** The mode in which to open the file */
enum eMode enum eMode
{ {
fmRead, // Read-only. If the file doesn't exist, object will not be valid 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 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); 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); cFile(const AString & iFileName, eMode iMode);
/// Auto-closes the file, if open /** Auto-closes the file, if open */
~cFile(); ~cFile();
bool Open(const AString & iFileName, eMode iMode); bool Open(const AString & iFileName, eMode iMode);
@ -77,60 +79,63 @@ public:
bool IsOpen(void) const; bool IsOpen(void) const;
bool IsEOF(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); 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); 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); 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; 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; 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); int ReadRestOfFile(AString & a_Contents);
// tolua_begin // tolua_begin
/// Returns true if the file specified exists /** Returns true if the file specified exists */
static bool Exists(const AString & a_FileName); 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); 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); 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); 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); 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); 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); 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); 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); static AString ReadWholeFile(const AString & a_FileName);
// tolua_end // 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 static AStringVector GetFolderContents(const AString & a_Folder); // Exported in ManualBindings.cpp
int Printf(const char * a_Fmt, ...); int Printf(const char * a_Fmt, ...);
/** Flushes all the bufferef output into the file (only when writing) */
void Flush(void);
private: private:
#ifdef USE_STDIO_FILE #ifdef USE_STDIO_FILE
FILE * m_File; FILE * m_File;

View File

@ -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) : cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
super(a_Client), super(a_Client),
m_ServerAddress(a_ServerAddress), 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_OutPacketLenBuffer(20), // 20 bytes is more than enough for one VarInt
m_IsEncrypted(false) 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) 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)) if (!m_ReceivedData.Write(a_Data, a_Size))
{ {
// Too much data in the incoming queue, report to caller: // 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; 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)) if (!HandlePacket(bb, PacketType))
{ {
// Unknown packet, already been reported, but without the length. Log the length here: // 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()); LOGD("Packet contents:\n%s", Out.c_str());
#endif // _DEBUG #endif // _DEBUG
// Put a message in the comm log:
if (g_ShouldLogComm)
{
m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n");
}
return; 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", 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 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!"); ASSERT(!"Read wrong number of bytes!");
m_Client->PacketError(PacketType); m_Client->PacketError(PacketType);
} }
@ -1807,6 +1879,17 @@ cProtocol172::cPacketizer::~cPacketizer()
m_Out.ReadAll(DataToSend); m_Out.ReadAll(DataToSend);
m_Protocol.SendData(DataToSend.data(), DataToSend.size()); m_Protocol.SendData(DataToSend.data(), DataToSend.size());
m_Out.CommitRead(); 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()
);
}
} }

View File

@ -222,6 +222,10 @@ protected:
cAESCFBDecryptor m_Decryptor; cAESCFBDecryptor m_Decryptor;
cAESCFBEncryptor m_Encryptor; 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 /// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets
void AddReceivedData(const char * a_Data, int a_Size); void AddReceivedData(const char * a_Data, int a_Size);

View File

@ -13,7 +13,8 @@
#include "../BlockEntities/DropSpenserEntity.h" #include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/EnderChestEntity.h" #include "../BlockEntities/EnderChestEntity.h"
#include "../BlockEntities/HopperEntity.h" #include "../BlockEntities/HopperEntity.h"
#include "../Root.h"
#include "../Bindings/PluginManager.h"
@ -169,6 +170,7 @@ void cWindow::Clicked(
const cItem & a_ClickedItem const cItem & a_ClickedItem
) )
{ {
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
if (a_WindowID != m_WindowID) 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()); 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: 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: // Toss one of the dragged items:
a_Player.TossItem(true); a_Player.TossHeldItem();
return; return;
} }
case caLeftClickOutside: 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: // Toss all dragged items:
a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount); a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount);
return; return;
} }
case caLeftClickOutsideHoldNothing: case caLeftClickOutsideHoldNothing:
@ -263,7 +286,7 @@ bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
if (a_Player.IsDraggingItem()) if (a_Player.IsDraggingItem())
{ {
LOGD("Player holds item! Dropping it..."); 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(); cClientHandle * ClientHandle = a_Player.GetClientHandle();

View File

@ -31,16 +31,12 @@ cScoreboardSerializer::cScoreboardSerializer(const AString & a_WorldName, cScore
bool cScoreboardSerializer::Load(void) bool cScoreboardSerializer::Load(void)
{ {
cFile File; AString Data = cFile::ReadWholeFile(FILE_IO_PREFIX + m_Path);
if (!File.Open(FILE_IO_PREFIX + m_Path, cFile::fmRead)) if (Data.empty())
{ {
return false; return false;
} }
AString Data;
File.ReadRestOfFile(Data);
File.Close();
AString Uncompressed; AString Uncompressed;
int res = UncompressStringGZIP(Data.data(), Data.size(), Uncompressed); int res = UncompressStringGZIP(Data.data(), Data.size(), Uncompressed);

View File

@ -1926,14 +1926,19 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N
double Speed[3]; double Speed[3];
if (!LoadDoublesListFromNBT(Speed, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Motion"))) 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]); a_Entity.SetSpeed(Speed[0], Speed[1], Speed[2]);
double Rotation[3]; double Rotation[3];
if (!LoadDoublesListFromNBT(Rotation, 2, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Rotation"))) 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.SetYaw(Rotation[0]);
a_Entity.SetRoll(Rotation[1]); a_Entity.SetRoll(Rotation[1]);

View File

@ -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 /// If defined, a thorough leak finder will be used (debug MSVC only); leaks will be output to the Output window
#define ENABLE_LEAK_FINDER #define ENABLE_LEAK_FINDER
@ -216,12 +223,24 @@ int main( int argc, char **argv )
#ifndef _DEBUG #ifndef _DEBUG
std::signal(SIGSEGV, NonCtrlHandler); std::signal(SIGSEGV, NonCtrlHandler);
std::signal(SIGTERM, NonCtrlHandler); std::signal(SIGTERM, NonCtrlHandler);
std::signal(SIGINT, NonCtrlHandler); std::signal(SIGINT, NonCtrlHandler);
#endif #endif
// DEBUG: test the dumpfile creation: // DEBUG: test the dumpfile creation:
// *((int *)0) = 0; // *((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) #if !defined(ANDROID_NDK)
try try
#endif #endif