1
0
Fork 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
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/

View File

@ -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.*
src\Bindings\Bindings.*

1
MCServer/.gitignore vendored
View File

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

View File

@ -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
}

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

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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:

View File

@ -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));
}
else
{
// Drop an item from the inventory:
if (a_bDraggingItem)
char NewAmount = a_Amount;
if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount)
{
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();
}
}
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::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 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;

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
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);

View File

@ -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);

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 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);

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()
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;

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) :
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()
);
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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]);

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
#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