1
0

Merge pull request #1826 from mc-server/UnifyPacketizer

Unify packetizer
This commit is contained in:
Mattes D 2015-03-24 13:09:41 +01:00
commit e5a7a730ed
48 changed files with 2414 additions and 2047 deletions

File diff suppressed because it is too large Load Diff

View File

@ -73,13 +73,15 @@
// Integral types with predefined sizes:
typedef long long Int64;
typedef int Int32;
typedef short Int16;
typedef signed long long Int64;
typedef signed int Int32;
typedef signed short Int16;
typedef signed char Int8;
typedef unsigned long long UInt64;
typedef unsigned int UInt32;
typedef unsigned short UInt16;
typedef unsigned char UInt8;
typedef unsigned char Byte;
@ -245,7 +247,3 @@ public:
#define LOGERROR printf
#define LOGINFO printf
#define LOGWARNING printf

View File

@ -5,6 +5,8 @@
#include "Globals.h"
#include "Server.h"
#include "../../src/Logger.h"
#include "../../src/LoggerListeners.h"
@ -12,8 +14,16 @@
int main(int argc, char ** argv)
{
// Initialize logging subsystem:
cLogger::InitiateMultithreading();
auto consoleLogListener = MakeConsoleListener();
auto fileLogListener = new cFileListener();
cLogger::GetInstance().AttachListener(consoleLogListener);
cLogger::GetInstance().AttachListener(fileLogListener);
int ListenPort = (argc > 1) ? atoi(argv[1]) : 25564;
int ConnectPort = (argc > 2) ? atoi(argv[2]) : 25565;
printf("Initializing ProtoProxy. Listen port %d, connect port %d.\n", ListenPort, ConnectPort);
cServer Server;
int res = Server.Init(ListenPort, ConnectPort);
if (res != 0)

View File

@ -6,6 +6,7 @@
#include "Globals.h"
#include "Server.h"
#include "Connection.h"
#include "../../src/Logger.h"
@ -28,15 +29,11 @@ int cServer::Init(short a_ListenPort, short a_ConnectPort)
int res = WSAStartup(0x0202, &wsa);
if (res != 0)
{
printf("Cannot initialize WinSock: %d\n", res);
LOGERROR("Cannot initialize WinSock: %d", res);
return res;
}
#endif // _WIN32
LOGINFO("Generating protocol encryption keypair...");
m_PrivateKey.Generate();
m_PublicKeyDER = m_PrivateKey.GetPubKeyDER();
m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_ListenSocket < 0)
{
@ -45,22 +42,22 @@ int cServer::Init(short a_ListenPort, short a_ConnectPort)
#else
int err = errno;
#endif
printf("Failed to create listener socket: %d\n", err);
LOGERROR("Failed to create listener socket: %d", err);
return err;
}
sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = 130; // INADDR_ANY; // All interfaces
local.sin_addr.s_addr = INADDR_ANY; // All interfaces
local.sin_port = htons(a_ListenPort);
if (!bind(m_ListenSocket, (sockaddr *)&local, sizeof(local)))
if (bind(m_ListenSocket, (sockaddr *)&local, sizeof(local)) != 0)
{
#ifdef _WIN32
int err = WSAGetLastError();
#else
int err = errno;
#endif
printf("Failed to bind listener socket: %d\n", err);
LOGERROR("Failed to bind listener socket: %d", err);
return err;
}
if (listen(m_ListenSocket, 1) != 0)
@ -73,9 +70,12 @@ int cServer::Init(short a_ListenPort, short a_ConnectPort)
printf("Failed to listen on socket: %d\n", err);
return err;
}
LOGINFO("Listening on port %d, connecting to localhost:%d", a_ListenPort, a_ConnectPort);
printf("Listening on port %d, connecting to localhost:%d\n", a_ListenPort, a_ConnectPort);
LOGINFO("Generating protocol encryption keypair...");
m_PrivateKey.Generate();
m_PublicKeyDER = m_PrivateKey.GetPubKeyDER();
return 0;
}

View File

@ -21,7 +21,7 @@ class cServer
SOCKET m_ListenSocket;
cRsaPrivateKey m_PrivateKey;
AString m_PublicKeyDER;
short m_ConnectPort;
UInt16 m_ConnectPort;
public:
cServer(void);
@ -32,7 +32,7 @@ public:
cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
const AString & GetPublicKeyDER (void) { return m_PublicKeyDER; }
short GetConnectPort(void) const { return m_ConnectPort; }
UInt16 GetConnectPort(void) const { return m_ConnectPort; }
} ;

View File

@ -590,7 +590,7 @@ static int tolua_DoWith(lua_State* tolua_S)
template <
class Ty1,
class Ty2,
bool (Ty1::*Func1)(int, cItemCallback<Ty2> &)
bool (Ty1::*Func1)(UInt32, cItemCallback<Ty2> &)
>
static int tolua_DoWithID(lua_State* tolua_S)
{
@ -3879,6 +3879,10 @@ void ManualBindings::Bind(lua_State * tolua_S)
BindRankManager(tolua_S);
BindNetwork(tolua_S);
tolua_beginmodule(tolua_S, "cEntity");
tolua_constant(tolua_S, "INVALID_ID", cEntity::INVALID_ID);
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
}

View File

@ -105,7 +105,7 @@ void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum)
{
double MobX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width);
double MobZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);
if (m_World->SpawnMob(MobX, DispY, MobZ, static_cast<eMonsterType>(m_Contents.GetSlot(a_SlotNum).m_ItemDamage)) >= 0)
if (m_World->SpawnMob(MobX, DispY, MobZ, static_cast<eMonsterType>(m_Contents.GetSlot(a_SlotNum).m_ItemDamage)) != cEntity::INVALID_ID)
{
m_Contents.ChangeSlotCount(a_SlotNum, -1);
}
@ -144,29 +144,37 @@ void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum)
case E_ITEM_FIRE_CHARGE:
{
SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkFireCharge, GetShootVector(Meta) * 20);
m_Contents.ChangeSlotCount(a_SlotNum, -1);
if (SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkFireCharge, GetShootVector(Meta) * 20) != cEntity::INVALID_ID)
{
m_Contents.ChangeSlotCount(a_SlotNum, -1);
}
break;
}
case E_ITEM_ARROW:
{
SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkArrow, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0));
m_Contents.ChangeSlotCount(a_SlotNum, -1);
if (SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkArrow, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0)) != cEntity::INVALID_ID)
{
m_Contents.ChangeSlotCount(a_SlotNum, -1);
}
break;
}
case E_ITEM_SNOWBALL:
{
SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkSnowball, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0));
m_Contents.ChangeSlotCount(a_SlotNum, -1);
if (SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkSnowball, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0)) != cEntity::INVALID_ID)
{
m_Contents.ChangeSlotCount(a_SlotNum, -1);
}
break;
}
case E_ITEM_EGG:
{
SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkEgg, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0));
m_Contents.ChangeSlotCount(a_SlotNum, -1);
if (SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkEgg, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0)) != cEntity::INVALID_ID)
{
m_Contents.ChangeSlotCount(a_SlotNum, -1);
}
break;
}
@ -188,9 +196,14 @@ void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum)
void cDispenserEntity::SpawnProjectileFromDispenser(int a_BlockX, int a_BlockY, int a_BlockZ, cProjectileEntity::eKind a_Kind, const Vector3d & a_ShootVector)
UInt32 cDispenserEntity::SpawnProjectileFromDispenser(int a_BlockX, int a_BlockY, int a_BlockZ, cProjectileEntity::eKind a_Kind, const Vector3d & a_ShootVector)
{
m_World->CreateProjectile(static_cast<double>(a_BlockX + 0.5), static_cast<double>(a_BlockY + 0.5), static_cast<double>(a_BlockZ + 0.5), a_Kind, nullptr, nullptr, &a_ShootVector);
return m_World->CreateProjectile(
static_cast<double>(a_BlockX + 0.5),
static_cast<double>(a_BlockY + 0.5),
static_cast<double>(a_BlockZ + 0.5),
a_Kind, nullptr, nullptr, &a_ShootVector
);
}

View File

@ -24,8 +24,9 @@ public:
// tolua_begin
/** Spawns a projectile of the given kind in front of the dispenser with the specified speed. */
void SpawnProjectileFromDispenser(int a_BlockX, int a_BlockY, int a_BlockZ, cProjectileEntity::eKind a_Kind, const Vector3d & a_Speed);
/** Spawns a projectile of the given kind in front of the dispenser with the specified speed.
Returns the UniqueID of the spawned projectile, or 0 on failure. */
UInt32 SpawnProjectileFromDispenser(int a_BlockX, int a_BlockY, int a_BlockZ, cProjectileEntity::eKind a_Kind, const Vector3d & a_Speed);
/** Returns a unit vector in the cardinal direction of where the dispenser is facing. */
Vector3d GetShootVector(NIBBLETYPE a_Meta);

View File

@ -169,7 +169,7 @@ void cMobSpawnerEntity::SpawnEntity(void)
Monster->SetPosition(PosX, RelY, PosZ);
Monster->SetYaw(Random.NextFloat() * 360.0f);
if (Chunk->GetWorld()->SpawnMobFinalize(Monster) != mtInvalidType)
if (Chunk->GetWorld()->SpawnMobFinalize(Monster) != cEntity::INVALID_ID)
{
EntitiesSpawned = true;
Chunk->BroadcastSoundParticleEffect(2004, (int)(PosX * 8.0), (int)(RelY * 8.0), (int)(PosZ * 8.0), 0);

View File

@ -30,14 +30,16 @@ public:
/** Spawns item pickups for each item in the list. May compress pickups if too many entities: */
virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false) = 0;
/** Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified: */
/** Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified. */
virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false) = 0;
/** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) = 0;
/** Spawns a mob of the specified type.
Returns the mob's UniqueID if recognized and spawned, or cEntity::INVALID_ID on failure. */
virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) = 0;
/** Spawns an experience orb at the given location with the given reward. It returns the UniqueID of the spawned experience orb. */
virtual int SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) = 0;
/** Spawns an experience orb at the given location with the given reward.
Returns the UniqueID of the spawned experience orb, or cEntity::INVALID_ID on failure. */
virtual UInt32 SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) = 0;
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) = 0;

View File

@ -81,9 +81,9 @@ public:
void TestWrite(void)
{
cByteBuffer buf(50);
buf.WriteVarInt(5);
buf.WriteVarInt(300);
buf.WriteVarInt(0);
buf.WriteVarInt32(5);
buf.WriteVarInt32(300);
buf.WriteVarInt32(0);
AString All;
buf.ReadAll(All);
assert_test(All.size() == 4);
@ -101,8 +101,8 @@ public:
assert_test(buf.Write("a", 1));
assert_test(buf.CanReadBytes(1));
assert_test(buf.GetReadableSpace() == 1);
unsigned char v = 0;
assert_test(buf.ReadByte(v));
UInt8 v = 0;
assert_test(buf.ReadBEUInt8(v));
assert_test(v == 'a');
assert_test(buf.GetReadableSpace() == 0);
buf.CommitRead();
@ -317,7 +317,7 @@ bool cByteBuffer::CanWriteBytes(size_t a_Count) const
bool cByteBuffer::ReadChar(char & a_Value)
bool cByteBuffer::ReadBEInt8(Int8 & a_Value)
{
CHECK_THREAD
CheckValid();
@ -330,7 +330,7 @@ bool cByteBuffer::ReadChar(char & a_Value)
bool cByteBuffer::ReadByte(unsigned char & a_Value)
bool cByteBuffer::ReadBEUInt8(UInt8 & a_Value)
{
CHECK_THREAD
CheckValid();
@ -343,15 +343,15 @@ bool cByteBuffer::ReadByte(unsigned char & a_Value)
bool cByteBuffer::ReadBEShort(short & a_Value)
bool cByteBuffer::ReadBEInt16(Int16 & a_Value)
{
CHECK_THREAD
CheckValid();
NEEDBYTES(2);
Int16 val;
UInt16 val;
ReadBuf(&val, 2);
val = ntohs(val);
a_Value = *(reinterpret_cast<short *>(&val));
memcpy(&a_Value, &val, 2);
return true;
}
@ -373,13 +373,15 @@ bool cByteBuffer::ReadBEUInt16(UInt16 & a_Value)
bool cByteBuffer::ReadBEInt(int & a_Value)
bool cByteBuffer::ReadBEInt32(Int32 & a_Value)
{
CHECK_THREAD
CheckValid();
NEEDBYTES(4);
ReadBuf(&a_Value, 4);
a_Value = (int)ntohl((u_long)a_Value);
UInt32 val;
ReadBuf(&val, 4);
val = ntohl(val);
memcpy(&a_Value, &val, 4);
return true;
}
@ -415,6 +417,20 @@ bool cByteBuffer::ReadBEInt64(Int64 & a_Value)
bool cByteBuffer::ReadBEUInt64(UInt64 & a_Value)
{
CHECK_THREAD
CheckValid();
NEEDBYTES(8);
ReadBuf(&a_Value, 8);
a_Value = NetworkToHostULong8(&a_Value);
return true;
}
bool cByteBuffer::ReadBEFloat(float & a_Value)
{
CHECK_THREAD
@ -448,7 +464,7 @@ bool cByteBuffer::ReadBool(bool & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(1);
char Value = 0;
UInt8 Value = 0;
ReadBuf(&Value, 1);
a_Value = (Value != 0);
return true;
@ -462,24 +478,19 @@ bool cByteBuffer::ReadBEUTF16String16(AString & a_Value)
{
CHECK_THREAD
CheckValid();
short Length;
if (!ReadBEShort(Length))
UInt16 Length;
if (!ReadBEUInt16(Length))
{
return false;
}
if (Length < 0)
{
ASSERT(!"Negative string length? Are you sure?");
return true;
}
return ReadUTF16String(a_Value, (size_t)Length);
return ReadUTF16String(a_Value, Length);
}
bool cByteBuffer::ReadVarInt(UInt32 & a_Value)
bool cByteBuffer::ReadVarInt32(UInt32 & a_Value)
{
CHECK_THREAD
CheckValid();
@ -490,7 +501,29 @@ bool cByteBuffer::ReadVarInt(UInt32 & a_Value)
{
NEEDBYTES(1);
ReadBuf(&b, 1);
Value = Value | (((UInt32)(b & 0x7f)) << Shift);
Value = Value | ((static_cast<UInt32>(b & 0x7f)) << Shift);
Shift += 7;
} while ((b & 0x80) != 0);
a_Value = Value;
return true;
}
bool cByteBuffer::ReadVarInt64(UInt64 & a_Value)
{
CHECK_THREAD
CheckValid();
UInt64 Value = 0;
int Shift = 0;
unsigned char b = 0;
do
{
NEEDBYTES(1);
ReadBuf(&b, 1);
Value = Value | ((static_cast<UInt64>(b & 0x7f)) << Shift);
Shift += 7;
} while ((b & 0x80) != 0);
a_Value = Value;
@ -540,7 +573,7 @@ bool cByteBuffer::ReadLEInt(int & a_Value)
bool cByteBuffer::ReadPosition(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
bool cByteBuffer::ReadPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
{
CHECK_THREAD
Int64 Value;
@ -565,7 +598,7 @@ bool cByteBuffer::ReadPosition(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
bool cByteBuffer::WriteChar(char a_Value)
bool cByteBuffer::WriteBEInt8(Int8 a_Value)
{
CHECK_THREAD
CheckValid();
@ -577,7 +610,7 @@ bool cByteBuffer::WriteChar(char a_Value)
bool cByteBuffer::WriteByte(unsigned char a_Value)
bool cByteBuffer::WriteBEUInt8(UInt8 a_Value)
{
CHECK_THREAD
CheckValid();
@ -589,33 +622,48 @@ bool cByteBuffer::WriteByte(unsigned char a_Value)
bool cByteBuffer::WriteBEShort(short a_Value)
bool cByteBuffer::WriteBEInt16(Int16 a_Value)
{
CHECK_THREAD
CheckValid();
PUTBYTES(2);
u_short Converted = htons((u_short)a_Value);
return WriteBuf(&Converted, 2);
UInt16 val;
memcpy(&val, &a_Value, 2);
val = htons(val);
return WriteBuf(&val, 2);
}
bool cByteBuffer::WriteBEUShort(unsigned short a_Value)
bool cByteBuffer::WriteBEUInt16(UInt16 a_Value)
{
CHECK_THREAD
CheckValid();
PUTBYTES(2);
u_short Converted = htons((u_short)a_Value);
return WriteBuf(&Converted, 2);
a_Value = htons(a_Value);
return WriteBuf(&a_Value, 2);
}
bool cByteBuffer::WriteBEInt(int a_Value)
bool cByteBuffer::WriteBEInt32(Int32 a_Value)
{
CHECK_THREAD
CheckValid();
PUTBYTES(4);
UInt32 Converted = HostToNetwork4(&a_Value);
return WriteBuf(&Converted, 4);
}
bool cByteBuffer::WriteBEUInt32(UInt32 a_Value)
{
CHECK_THREAD
CheckValid();
@ -641,6 +689,19 @@ bool cByteBuffer::WriteBEInt64(Int64 a_Value)
bool cByteBuffer::WriteBEUInt64(UInt64 a_Value)
{
CHECK_THREAD
CheckValid();
PUTBYTES(8);
UInt64 Converted = HostToNetwork8(&a_Value);
return WriteBuf(&Converted, 8);
}
bool cByteBuffer::WriteBEFloat(float a_Value)
{
CHECK_THREAD
@ -672,14 +733,15 @@ bool cByteBuffer::WriteBool(bool a_Value)
{
CHECK_THREAD
CheckValid();
return WriteChar(a_Value ? 1 : 0);
UInt8 val = a_Value ? 1 : 0;
return Write(&val, 1);
}
bool cByteBuffer::WriteVarInt(UInt32 a_Value)
bool cByteBuffer::WriteVarInt32(UInt32 a_Value)
{
CHECK_THREAD
CheckValid();
@ -700,12 +762,35 @@ bool cByteBuffer::WriteVarInt(UInt32 a_Value)
bool cByteBuffer::WriteVarInt64(UInt64 a_Value)
{
CHECK_THREAD
CheckValid();
// A 64-bit integer can be encoded by at most 10 bytes:
unsigned char b[10];
size_t idx = 0;
do
{
b[idx] = (a_Value & 0x7f) | ((a_Value > 0x7f) ? 0x80 : 0x00);
a_Value = a_Value >> 7;
idx++;
} while (a_Value > 0);
return WriteBuf(b, idx);
}
bool cByteBuffer::WriteVarUTF8String(const AString & a_Value)
{
CHECK_THREAD
CheckValid();
PUTBYTES(a_Value.size() + 1); // This is a lower-bound on the bytes that will be actually written. Fail early.
bool res = WriteVarInt((UInt32)(a_Value.size()));
bool res = WriteVarInt32(static_cast<UInt32>(a_Value.size()));
if (!res)
{
return false;
@ -717,15 +802,15 @@ bool cByteBuffer::WriteVarUTF8String(const AString & a_Value)
bool cByteBuffer::WriteLEInt(int a_Value)
bool cByteBuffer::WriteLEInt32(Int32 a_Value)
{
CHECK_THREAD
CheckValid();
#ifdef IS_LITTLE_ENDIAN
return WriteBuf((const char *)&a_Value, 4);
return WriteBuf(reinterpret_cast<const char *>(&a_Value), 4);
#else
int Value = ((a_Value >> 24) & 0xff) | ((a_Value >> 16) & 0xff00) | ((a_Value >> 8) & 0xff0000) | (a_Value & 0xff000000);
return WriteBuf((const char *)&Value, 4);
return WriteBuf(reinterpret_cast<const char *>(&Value), 4);
#endif
}
@ -733,10 +818,15 @@ bool cByteBuffer::WriteLEInt(int a_Value)
bool cByteBuffer::WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ)
bool cByteBuffer::WritePosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ)
{
CHECK_THREAD
return WriteBEInt64(((Int64)a_BlockX & 0x3FFFFFF) << 38 | ((Int64)a_BlockY & 0xFFF) << 26 | ((Int64)a_BlockZ & 0x3FFFFFF));
CheckValid();
return WriteBEInt64(
(static_cast<Int64>(a_BlockX & 0x3FFFFFF) << 38) |
(static_cast<Int64>(a_BlockY & 0xFFF) << 26) |
(static_cast<Int64>(a_BlockZ & 0x3FFFFFF))
);
}

View File

@ -52,48 +52,53 @@ public:
bool CanWriteBytes(size_t a_Count) const;
// Read the specified datatype and advance the read pointer; return true if successfully read:
bool ReadChar (char & a_Value);
bool ReadByte (unsigned char & a_Value);
bool ReadBEShort (short & a_Value);
bool ReadBEUInt16 (UInt16 & a_Value);
bool ReadBEInt (int & a_Value);
bool ReadBEUInt32 (UInt32 & a_Value);
bool ReadBEInt8 (Int8 & a_Value);
bool ReadBEInt16 (Int16 & a_Value);
bool ReadBEInt32 (Int32 & a_Value);
bool ReadBEInt64 (Int64 & a_Value);
bool ReadBEUInt8 (UInt8 & a_Value);
bool ReadBEUInt16 (UInt16 & a_Value);
bool ReadBEUInt32 (UInt32 & a_Value);
bool ReadBEUInt64 (UInt64 & a_Value);
bool ReadBEFloat (float & a_Value);
bool ReadBEDouble (double & a_Value);
bool ReadBool (bool & a_Value);
bool ReadBEUTF16String16(AString & a_Value); // string length as BE short, then string as UTF-16BE
bool ReadVarInt (UInt32 & a_Value);
bool ReadVarInt32 (UInt32 & a_Value);
bool ReadVarInt64 (UInt64 & a_Value);
bool ReadVarUTF8String (AString & a_Value); // string length as VarInt, then string as UTF-8
bool ReadLEInt (int & a_Value);
bool ReadPosition (int & a_BlockX, int & a_BlockY, int & a_BlockZ);
bool ReadPosition64 (int & a_BlockX, int & a_BlockY, int & a_BlockZ);
/** Reads VarInt, assigns it to anything that can be assigned from an UInt32 (unsigned short, char, Byte, double, ...) */
/** Reads VarInt, assigns it to anything that can be assigned from an UInt64 (unsigned short, char, Byte, double, ...) */
template <typename T> bool ReadVarInt(T & a_Value)
{
UInt32 v;
bool res = ReadVarInt(v);
UInt64 v;
bool res = ReadVarInt64(v);
if (res)
{
a_Value = v;
a_Value = static_cast<T>(v);
}
return res;
}
// Write the specified datatype; return true if successfully written
bool WriteChar (char a_Value);
bool WriteByte (unsigned char a_Value);
bool WriteBEShort (short a_Value);
bool WriteBEUShort (unsigned short a_Value);
bool WriteBEInt (int a_Value);
bool WriteBEInt8 (Int8 a_Value);
bool WriteBEInt16 (Int16 a_Value);
bool WriteBEInt32 (Int32 a_Value);
bool WriteBEInt64 (Int64 a_Value);
bool WriteBEUInt8 (UInt8 a_Value);
bool WriteBEUInt16 (UInt16 a_Value);
bool WriteBEUInt32 (UInt32 a_Value);
bool WriteBEUInt64 (UInt64 a_Value);
bool WriteBEFloat (float a_Value);
bool WriteBEDouble (double a_Value);
bool WriteBool (bool a_Value);
bool WriteVarInt (UInt32 a_Value);
bool WriteVarInt32 (UInt32 a_Value);
bool WriteVarInt64 (UInt64 a_Value);
bool WriteVarUTF8String (const AString & a_Value); // string length as VarInt, then string as UTF-8
bool WriteLEInt (int a_Value);
bool WritePosition (int a_BlockX, int a_BlockY, int a_BlockZ);
bool WriteLEInt32 (Int32 a_Value);
bool WritePosition64 (Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ);
/** Reads a_Count bytes into a_Buffer; returns true if successful */
bool ReadBuf(void * a_Buffer, size_t a_Count);

View File

@ -1969,7 +1969,7 @@ void cChunk::RemoveEntity(cEntity * a_Entity)
bool cChunk::HasEntity(int a_EntityID)
bool cChunk::HasEntity(UInt32 a_EntityID)
{
for (cEntityList::const_iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr)
{
@ -2027,7 +2027,7 @@ bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_
bool cChunk::DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult)
bool cChunk::DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult)
{
// The entity list is locked by the parent chunkmap's CS
for (cEntityList::iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr)
@ -2814,7 +2814,7 @@ void cChunk::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char
void cChunk::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude)
void cChunk::BroadcastBlockBreakAnimation(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude)
{
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@ -2822,7 +2822,7 @@ void cChunk::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_bl
{
continue;
}
(*itr)->SendBlockBreakAnim(a_entityID, a_blockX, a_blockY, a_blockZ, a_stage);
(*itr)->SendBlockBreakAnim(a_EntityID, a_BlockX, a_BlockY, a_BlockZ, a_Stage);
} // for itr - LoadedByClient[]
}

View File

@ -241,7 +241,7 @@ public:
void AddEntity(cEntity * a_Entity);
void RemoveEntity(cEntity * a_Entity);
bool HasEntity(int a_EntityID);
bool HasEntity(UInt32 a_EntityID);
/** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
@ -251,7 +251,7 @@ public:
bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Lua-accessible
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible
bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible
/** Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true */
bool ForEachBlockEntity(cBlockEntityCallback & a_Callback); // Lua-accessible
@ -317,7 +317,7 @@ public:
// (Please keep these alpha-sorted)
void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
void BroadcastBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr);
void BroadcastBlockBreakAnimation(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = nullptr);
void BroadcastBlockBreakAnimation(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = nullptr);
void BroadcastBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = nullptr);
void BroadcastChunkData (cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = nullptr);
void BroadcastCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr);

View File

@ -373,19 +373,19 @@ void cChunkMap::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, c
void cChunkMap::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude)
void cChunkMap::BroadcastBlockBreakAnimation(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_blockX, a_blockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if (Chunk == nullptr)
{
return;
}
// It's perfectly legal to broadcast packets even to invalid chunks!
Chunk->BroadcastBlockBreakAnimation(a_entityID, a_blockX, a_blockY, a_blockZ, a_stage, a_Exclude);
Chunk->BroadcastBlockBreakAnimation(a_EntityID, a_BlockX, a_BlockY, a_BlockZ, a_Stage, a_Exclude);
}
@ -1753,7 +1753,7 @@ void cChunkMap::AddEntityIfNotPresent(cEntity * a_Entity)
bool cChunkMap::HasEntity(int a_UniqueID)
bool cChunkMap::HasEntity(UInt32 a_UniqueID)
{
cCSLock Lock(m_CSLayers);
for (cChunkLayerList::const_iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
@ -2045,7 +2045,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
bool cChunkMap::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback)
bool cChunkMap::DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
bool res = false;
@ -2996,7 +2996,7 @@ bool cChunkMap::cChunkLayer::ForEachEntity(cEntityCallback & a_Callback)
bool cChunkMap::cChunkLayer::DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackReturn)
bool cChunkMap::cChunkLayer::DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackReturn)
{
// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found.
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); i++)
@ -3016,7 +3016,7 @@ bool cChunkMap::cChunkLayer::DoWithEntityByID(int a_EntityID, cEntityCallback &
bool cChunkMap::cChunkLayer::HasEntity(int a_EntityID)
bool cChunkMap::cChunkLayer::HasEntity(UInt32 a_EntityID)
{
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); i++)
{

View File

@ -71,7 +71,7 @@ public:
// (Please keep these alpha-sorted)
void BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle);
void BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr);
void BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude = nullptr);
void BroadcastBlockBreakAnimation(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = nullptr);
void BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude);
void BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = nullptr);
void BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr);
@ -217,7 +217,7 @@ public:
void AddEntityIfNotPresent(cEntity * a_Entity);
/** Returns true if the entity with specified ID is present in the chunks */
bool HasEntity(int a_EntityID);
bool HasEntity(UInt32 a_EntityID);
/** Removes the entity from its appropriate chunk */
void RemoveEntity(cEntity * a_Entity);
@ -236,61 +236,80 @@ public:
/** Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates */
void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlockAffected);
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. */
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param.
Returns true if entity found and callback returned false. */
bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback); // Lua-accessible
/** Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true */
/** Calls the callback for each block entity in the specified chunk.
Returns true if all block entities processed, false if the callback aborted by returning true. */
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback); // Lua-accessible
/** Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true */
/** Calls the callback for each chest in the specified chunk.
Returns true if all chests processed, false if the callback aborted by returning true. */
bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Lua-accessible
/** Calls the callback for each dispenser in the specified chunk; returns true if all dispensers processed, false if the callback aborted by returning true */
/** Calls the callback for each dispenser in the specified chunk.
Returns true if all dispensers processed, false if the callback aborted by returning true. */
bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback & a_Callback);
/** Calls the callback for each dropper in the specified chunk; returns true if all droppers processed, false if the callback aborted by returning true */
/** Calls the callback for each dropper in the specified chunk.
Returns true if all droppers processed, false if the callback aborted by returning true. */
bool ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback & a_Callback);
/** Calls the callback for each dropspenser in the specified chunk; returns true if all dropspensers processed, false if the callback aborted by returning true */
/** Calls the callback for each dropspenser in the specified chunk.
Returns true if all dropspensers processed, false if the callback aborted by returning true. */
bool ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback & a_Callback);
/** Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true */
/** Calls the callback for each furnace in the specified chunk.
Returns true if all furnaces processed, false if the callback aborted by returning true. */
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback); // Lua-accessible
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
/** Calls the callback for the block entity at the specified coords.
Returns false if there's no block entity at those coords, true if found. */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
/** Calls the callback for the beacon at the specified coords.
Returns false if there's no beacon at those coords, true if found. */
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
/** Calls the callback for the chest at the specified coords.
Returns false if there's no chest at those coords, true if found. */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible
/** Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found */
/** Calls the callback for the dispenser at the specified coords.
Returns false if there's no dispenser at those coords or callback returns true, returns true if found. */
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback); // Lua-accessible
/** Calls the callback for the dropper at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found */
/** Calls the callback for the dropper at the specified coords.
Returns false if there's no dropper at those coords or callback returns true, returns true if found. */
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback); // Lua-accessible
/** Calls the callback for the dropspenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found */
/** Calls the callback for the dropspenser at the specified coords.
Returns false if there's no dropspenser at those coords or callback returns true, returns true if found. */
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback); // Lua-accessible
/** Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found */
/** Calls the callback for the furnace at the specified coords.
Returns false if there's no furnace at those coords or callback returns true, returns true if found. */
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible
/** Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found */
/** Calls the callback for the noteblock at the specified coords.
Returns false if there's no noteblock at those coords or callback returns true, returns true if found. */
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Lua-accessible
/** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
/** Calls the callback for the command block at the specified coords.
Returns false if there's no command block at those coords or callback returns true, returns true if found. */
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Lua-accessible
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
/** Calls the callback for the mob head block at the specified coords.
Returns false if there's no mob head block at those coords or callback returns true, returns true if found. */
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback); // Lua-accessible
/** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */
/** Calls the callback for the flower pot at the specified coords.
Returns false if there's no flower pot at those coords or callback returns true, returns true if found. */
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback); // Lua-accessible
/** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
/** Retrieves the test on the sign at the specified coords.
Returns false if there's no sign at those coords, true if found. */
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
/** Touches the chunk, causing it to be loaded or generated */
@ -423,10 +442,10 @@ private:
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackReturn); // Lua-accessible
bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackReturn); // Lua-accessible
/** Returns true if there is an entity with the specified ID within this layer's chunks */
bool HasEntity(int a_EntityID);
bool HasEntity(UInt32 a_EntityID);
protected:

View File

@ -676,7 +676,7 @@ bool cClientHandle::HandleLogin(int a_ProtocolVersion, const AString & a_Usernam
void cClientHandle::HandleCreativeInventory(short a_SlotNum, const cItem & a_HeldItem)
void cClientHandle::HandleCreativeInventory(Int16 a_SlotNum, const cItem & a_HeldItem, eClickAction a_ClickAction)
{
// This is for creative Inventory changes
if (!m_Player->IsGameModeCreative())
@ -690,18 +690,18 @@ void cClientHandle::HandleCreativeInventory(short a_SlotNum, const cItem & a_Hel
return;
}
m_Player->GetWindow()->Clicked(*m_Player, 0, a_SlotNum, (a_SlotNum >= 0) ? caLeftClick : caLeftClickOutside, a_HeldItem);
m_Player->GetWindow()->Clicked(*m_Player, 0, a_SlotNum, a_ClickAction, a_HeldItem);
}
void cClientHandle::HandleEnchantItem(Byte a_WindowID, Byte a_Enchantment)
void cClientHandle::HandleEnchantItem(UInt8 a_WindowID, UInt8 a_Enchantment)
{
if (a_Enchantment > 2)
{
LOGWARNING("%s attempt to crash the server with invalid enchanting selection!", GetUsername().c_str());
LOGWARNING("%s attempt to crash the server with invalid enchanting selection (%u)!", GetUsername().c_str(), a_Enchantment);
Kick("Invalid enchanting!");
return;
}
@ -951,7 +951,7 @@ void cClientHandle::HandleCommandBlockBlockChange(int a_BlockX, int a_BlockY, in
void cClientHandle::HandleCommandBlockEntityChange(int a_EntityID, const AString & a_NewCommand)
void cClientHandle::HandleCommandBlockEntityChange(UInt32 a_EntityID, const AString & a_NewCommand)
{
// TODO
LOGWARNING("%s: Not implemented yet", __FUNCTION__);
@ -978,7 +978,7 @@ void cClientHandle::HandleAnvilItemName(const AString & a_ItemName)
void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, char a_Status)
void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, UInt8 a_Status)
{
LOGD("HandleLeftClick: {%i, %i, %i}; Face: %i; Stat: %i",
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status
@ -1515,7 +1515,7 @@ void cClientHandle::HandleAnimation(int a_Animation)
void cClientHandle::HandleSlotSelected(short a_SlotNum)
void cClientHandle::HandleSlotSelected(Int16 a_SlotNum)
{
m_Player->GetInventory().SetEquippedSlotNum(a_SlotNum);
m_Player->GetWorld()->BroadcastEntityEquipment(*m_Player, 0, m_Player->GetInventory().GetEquippedItem(), this);
@ -1534,7 +1534,7 @@ void cClientHandle::HandleSteerVehicle(float a_Forward, float a_Sideways)
void cClientHandle::HandleWindowClose(char a_WindowID)
void cClientHandle::HandleWindowClose(UInt8 a_WindowID)
{
m_Player->CloseWindowIfID(a_WindowID);
}
@ -1543,7 +1543,7 @@ void cClientHandle::HandleWindowClose(char a_WindowID)
void cClientHandle::HandleWindowClick(char a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_HeldItem)
void cClientHandle::HandleWindowClick(UInt8 a_WindowID, Int16 a_SlotNum, eClickAction a_ClickAction, const cItem & a_HeldItem)
{
LOGD("WindowClick: WinID %d, SlotNum %d, action: %s, Item %s x %d",
a_WindowID, a_SlotNum, ClickActionToString(a_ClickAction),
@ -1581,7 +1581,7 @@ void cClientHandle::HandleUpdateSign(
void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick)
void cClientHandle::HandleUseEntity(UInt32 a_TargetEntityID, bool a_IsLeftClick)
{
// TODO: Let plugins interfere via a hook
@ -1726,7 +1726,7 @@ bool cClientHandle::HandleHandshake(const AString & a_Username)
void cClientHandle::HandleEntityCrouch(int a_EntityID, bool a_IsCrouching)
void cClientHandle::HandleEntityCrouch(UInt32 a_EntityID, bool a_IsCrouching)
{
if (a_EntityID != m_Player->GetUniqueID())
{
@ -1741,7 +1741,7 @@ void cClientHandle::HandleEntityCrouch(int a_EntityID, bool a_IsCrouching)
void cClientHandle::HandleEntityLeaveBed(int a_EntityID)
void cClientHandle::HandleEntityLeaveBed(UInt32 a_EntityID)
{
if (a_EntityID != m_Player->GetUniqueID())
{
@ -1758,7 +1758,7 @@ void cClientHandle::HandleEntityLeaveBed(int a_EntityID)
void cClientHandle::HandleEntitySprinting(int a_EntityID, bool a_IsSprinting)
void cClientHandle::HandleEntitySprinting(UInt32 a_EntityID, bool a_IsSprinting)
{
if (a_EntityID != m_Player->GetUniqueID())
{
@ -2030,7 +2030,7 @@ void cClientHandle::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, ch
void cClientHandle::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage)
void cClientHandle::SendBlockBreakAnim(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage)
{
m_Protocol->SendBlockBreakAnim(a_EntityID, a_BlockX, a_BlockY, a_BlockZ, a_Stage);
}

View File

@ -144,7 +144,7 @@ public: // tolua_export
// (Please keep these alpha-sorted)
void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType);
void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage);
void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage);
void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_export
void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes);
void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
@ -276,16 +276,18 @@ public: // tolua_export
/** Called when the protocol receives a MC|AdvCdm plugin message, indicating that the player set a new
command in the command block UI, for an entity-based commandblock (minecart?). */
void HandleCommandBlockEntityChange(int a_EntityID, const AString & a_NewCommand);
void HandleCommandBlockEntityChange(UInt32 a_EntityID, const AString & a_NewCommand);
void HandleCreativeInventory (short a_SlotNum, const cItem & a_HeldItem);
/** Called when the client clicks the creative inventory window.
a_ClickAction specifies whether the click was inside the window or not (caLeftClick or caLeftClickOutside). */
void HandleCreativeInventory(Int16 a_SlotNum, const cItem & a_HeldItem, eClickAction a_ClickAction);
/** Called when the player enchants an Item in the Enchanting table UI. */
void HandleEnchantItem(Byte a_WindowID, Byte a_Enchantment);
void HandleEnchantItem(UInt8 a_WindowID, UInt8 a_Enchantment);
void HandleEntityCrouch (int a_EntityID, bool a_IsCrouching);
void HandleEntityLeaveBed (int a_EntityID);
void HandleEntitySprinting (int a_EntityID, bool a_IsSprinting);
void HandleEntityCrouch (UInt32 a_EntityID, bool a_IsCrouching);
void HandleEntityLeaveBed (UInt32 a_EntityID);
void HandleEntitySprinting (UInt32 a_EntityID, bool a_IsSprinting);
/** Kicks the client if the same username is already logged in.
Returns false if the client has been kicked, true otherwise. */
@ -298,7 +300,7 @@ public: // tolua_export
bool HandleHandshake (const AString & a_Username);
void HandleKeepAlive (int a_KeepAliveID);
void HandleLeftClick (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, char a_Status);
void HandleLeftClick (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, UInt8 a_Status);
/** Called when the protocol receives a MC|TrSel packet, indicating that the player used a trade in
the NPC UI. */
@ -312,7 +314,7 @@ public: // tolua_export
void HandlePluginMessage (const AString & a_Channel, const AString & a_Message);
void HandleRespawn (void);
void HandleRightClick (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem);
void HandleSlotSelected (short a_SlotNum);
void HandleSlotSelected (Int16 a_SlotNum);
void HandleSteerVehicle (float Forward, float Sideways);
void HandleTabCompletion (const AString & a_Text);
void HandleUpdateSign (
@ -321,9 +323,9 @@ public: // tolua_export
const AString & a_Line3, const AString & a_Line4
);
void HandleUnmount (void);
void HandleUseEntity (int a_TargetEntityID, bool a_IsLeftClick);
void HandleWindowClick (char a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_HeldItem);
void HandleWindowClose (char a_WindowID);
void HandleUseEntity (UInt32 a_TargetEntityID, bool a_IsLeftClick);
void HandleWindowClick (UInt8 a_WindowID, Int16 a_SlotNum, eClickAction a_ClickAction, const cItem & a_HeldItem);
void HandleWindowClose (UInt8 a_WindowID);
/** Called when the protocol has finished logging the user in.
Return true to allow the user in; false to kick them.

View File

@ -59,6 +59,18 @@ inline Int64 NetworkToHostLong8(const void * a_Value)
inline UInt64 NetworkToHostULong8(const void * a_Value)
{
UInt64 buf;
memcpy(&buf, a_Value, 8);
buf = ntohll(buf);
return buf;
}
inline float NetworkToHostFloat4(const void * a_Value)
{
UInt32 buf;

View File

@ -18,49 +18,50 @@
int cEntity::m_EntityCount = 0;
UInt32 cEntity::m_EntityCount = 0;
cCriticalSection cEntity::m_CSCount;
cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height)
: m_UniqueID(0)
, m_Health(1)
, m_MaxHealth(1)
, m_AttachedTo(nullptr)
, m_Attachee(nullptr)
, m_bDirtyHead(true)
, m_bDirtyOrientation(true)
, m_bHasSentNoSpeed(true)
, m_bOnGround(false)
, m_Gravity(-9.81f)
, m_LastPos(a_X, a_Y, a_Z)
, m_IsInitialized(false)
, m_WorldTravellingFrom(nullptr)
, m_EntityType(a_EntityType)
, m_World(nullptr)
, m_IsFireproof(false)
, m_TicksSinceLastBurnDamage(0)
, m_TicksSinceLastLavaDamage(0)
, m_TicksSinceLastFireDamage(0)
, m_TicksLeftBurning(0)
, m_TicksSinceLastVoidDamage(0)
, m_IsSwimming(false)
, m_IsSubmerged(false)
, m_AirLevel(0)
, m_AirTickTimer(0)
, m_TicksAlive(0)
, m_HeadYaw(0.0)
, m_Rot(0.0, 0.0, 0.0)
, m_Pos(a_X, a_Y, a_Z)
, m_WaterSpeed(0, 0, 0)
, m_Mass (0.001) // Default 1g
, m_Width(a_Width)
, m_Height(a_Height)
, m_InvulnerableTicks(0)
cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height):
m_UniqueID(INVALID_ID), // Proper ID will be assigned later in the constructor code
m_Health(1),
m_MaxHealth(1),
m_AttachedTo(nullptr),
m_Attachee(nullptr),
m_bDirtyHead(true),
m_bDirtyOrientation(true),
m_bHasSentNoSpeed(true),
m_bOnGround(false),
m_Gravity(-9.81f),
m_LastPos(a_X, a_Y, a_Z),
m_IsInitialized(false),
m_WorldTravellingFrom(nullptr),
m_EntityType(a_EntityType),
m_World(nullptr),
m_IsFireproof(false),
m_TicksSinceLastBurnDamage(0),
m_TicksSinceLastLavaDamage(0),
m_TicksSinceLastFireDamage(0),
m_TicksLeftBurning(0),
m_TicksSinceLastVoidDamage(0),
m_IsSwimming(false),
m_IsSubmerged(false),
m_AirLevel(0),
m_AirTickTimer(0),
m_TicksAlive(0),
m_HeadYaw(0.0),
m_Rot(0.0, 0.0, 0.0),
m_Pos(a_X, a_Y, a_Z),
m_WaterSpeed(0, 0, 0),
m_Mass (0.001), // Default 1g
m_Width(a_Width),
m_Height(a_Height),
m_InvulnerableTicks(0)
{
// Assign a proper ID:
cCSLock Lock(m_CSCount);
m_EntityCount++;
m_UniqueID = m_EntityCount;

View File

@ -142,6 +142,10 @@ public:
static const int VOID_BOUNDARY = -46; ///< Y position to begin applying void damage
static const int FALL_DAMAGE_HEIGHT = 4; ///< Y difference after which fall damage is applied
/** Special ID that is considered an "invalid value", signifying no entity. */
static const UInt32 INVALID_ID = 0; // Exported to Lua in ManualBindings.cpp, ToLua doesn't parse initialized constants.
cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
virtual ~cEntity();
@ -248,7 +252,7 @@ public:
virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways);
void SteerVehicle(float a_Forward, float a_Sideways);
inline int GetUniqueID(void) const { return m_UniqueID; }
inline UInt32 GetUniqueID(void) const { return m_UniqueID; }
inline bool IsDestroyed(void) const { return !m_IsInitialized; }
/// Schedules the entity for destroying; if a_ShouldBroadcast is set to true, broadcasts the DestroyEntity packet
@ -464,12 +468,15 @@ public:
protected:
static cCriticalSection m_CSCount;
static int m_EntityCount;
static UInt32 m_EntityCount;
/** Measured in meter/second (m/s) */
Vector3d m_Speed;
int m_UniqueID;
/** The ID of the entity that is guaranteed to be unique within a single run of the server.
Always nonzero (a zero UniqueID (cEntity::INVALID_ID) is used for error reporting).
Note that the UniqueID is not persisted through storage. */
UInt32 m_UniqueID;
int m_Health;
int m_MaxHealth;

View File

@ -24,7 +24,7 @@ public:
// tolua_begin
/** Returns the item in the frame */
const cItem & GetItem(void) { return m_Item; }
const cItem & GetItem(void) const { return m_Item; }
/** Set the item in the frame */
void SetItem(cItem & a_Item) { m_Item = a_Item; }

View File

@ -24,7 +24,7 @@ class cMinecartCollisionCallback :
public cEntityCallback
{
public:
cMinecartCollisionCallback(Vector3d a_Pos, double a_Height, double a_Width, int a_UniqueID, int a_AttacheeUniqueID) :
cMinecartCollisionCallback(Vector3d a_Pos, double a_Height, double a_Width, UInt32 a_UniqueID, UInt32 a_AttacheeUniqueID) :
m_DoesInteserct(false),
m_CollidedEntityPos(0, 0, 0),
m_Pos(a_Pos),
@ -77,8 +77,8 @@ protected:
Vector3d m_Pos;
double m_Height, m_Width;
int m_UniqueID;
int m_AttacheeUniqueID;
UInt32 m_UniqueID;
UInt32 m_AttacheeUniqueID;
};
@ -824,7 +824,10 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta)
{
cMinecartCollisionCallback MinecartCollisionCallback(GetPosition(), GetHeight(), GetWidth(), GetUniqueID(), ((m_Attachee == nullptr) ? -1 : m_Attachee->GetUniqueID()));
cMinecartCollisionCallback MinecartCollisionCallback(
GetPosition(), GetHeight(), GetWidth(), GetUniqueID(),
((m_Attachee == nullptr) ? cEntity::INVALID_ID : m_Attachee->GetUniqueID())
);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(POSX_TOINT, POSZ_TOINT, ChunkX, ChunkZ);
m_World->ForEachEntityInChunk(ChunkX, ChunkZ, MinecartCollisionCallback);

View File

@ -221,7 +221,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a
super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
m_ProjectileKind(a_Kind),
m_CreatorData(
((a_Creator != nullptr) ? a_Creator->GetUniqueID() : -1),
((a_Creator != nullptr) ? a_Creator->GetUniqueID() : cEntity::INVALID_ID),
((a_Creator != nullptr) ? (a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : "") : ""),
((a_Creator != nullptr) ? a_Creator->GetEquippedWeapon().m_Enchantments : cEnchantments())
),

View File

@ -69,7 +69,7 @@ public:
/** Returns the unique ID of the entity who created this projectile
May return an ID <0
*/
int GetCreatorUniqueID(void) { return m_CreatorData.m_UniqueID; }
UInt32 GetCreatorUniqueID(void) { return m_CreatorData.m_UniqueID; }
/** Returns the name of the player that created the projectile
Will be empty for non-player creators
@ -90,18 +90,17 @@ public:
protected:
/** A structure that stores the Entity ID and Playername of the projectile's creator
Used to migitate invalid pointers caused by the creator being destroyed
*/
Used to migitate invalid pointers caused by the creator being destroyed. */
struct CreatorData
{
CreatorData(int a_UniqueID, const AString & a_Name, const cEnchantments & a_Enchantments) :
CreatorData(UInt32 a_UniqueID, const AString & a_Name, const cEnchantments & a_Enchantments) :
m_UniqueID(a_UniqueID),
m_Name(a_Name),
m_Enchantments(a_Enchantments)
{
}
const int m_UniqueID;
const UInt32 m_UniqueID;
AString m_Name;
cEnchantments m_Enchantments;
};
@ -110,8 +109,7 @@ protected:
eKind m_ProjectileKind;
/** The structure for containing the entity ID and name who has created this projectile
The ID and/or name may be nullptr (e.g. for dispensers/mobs)
*/
The ID and/or name may be nullptr (e.g. for dispensers/mobs). */
CreatorData m_CreatorData;
/** True if the projectile has hit the ground and is stuck there */

View File

@ -132,13 +132,15 @@
// Integral types with predefined sizes:
typedef long long Int64;
typedef int Int32;
typedef short Int16;
typedef signed long long Int64;
typedef signed int Int32;
typedef signed short Int16;
typedef signed char Int8;
typedef unsigned long long UInt64;
typedef unsigned int UInt32;
typedef unsigned short UInt16;
typedef unsigned char UInt8;
typedef unsigned char Byte;
@ -156,10 +158,12 @@ class SizeChecker<T, Size, true>
template class SizeChecker<Int64, 8>;
template class SizeChecker<Int32, 4>;
template class SizeChecker<Int16, 2>;
template class SizeChecker<Int8, 1>;
template class SizeChecker<UInt64, 8>;
template class SizeChecker<UInt32, 4>;
template class SizeChecker<UInt16, 2>;
template class SizeChecker<UInt8, 1>;
// A macro to disallow the copy constructor and operator = functions
// This should be used in the private: declarations for any class that shouldn't allow copying itself

View File

@ -39,7 +39,7 @@ public:
Vector3d Pos = a_Player->GetThrowStartPos();
Vector3d Speed = a_Player->GetLookVector() * 7;
if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity::pkSplashPotion, a_Player, &a_Player->GetEquippedItem(), &Speed) < 0)
if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity::pkSplashPotion, a_Player, &a_Player->GetEquippedItem(), &Speed) == cEntity::INVALID_ID)
{
return false;
}

View File

@ -36,7 +36,7 @@ public:
eMonsterType MonsterType = ItemDamageToMonsterType(a_Item.m_ItemDamage);
if (
(MonsterType != mtInvalidType) && // Valid monster type
(a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType) >= 0)) // Spawning succeeded
(a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType) != cEntity::INVALID_ID)) // Spawning succeeded
{
if (!a_Player->IsGameModeCreative())
{

View File

@ -35,7 +35,7 @@ public:
cFastRandom Random;
a_World->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY() - a_Player->GetHeight(), a_Player->GetPosZ(), 0.5f, 0.4f / (Random.NextFloat(1.0f) * 0.4f + 0.8f));
if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem(), &Speed) < 0)
if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem(), &Speed) == cEntity::INVALID_ID)
{
return false;
}
@ -135,7 +135,7 @@ public:
return false;
}
if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem()) < 0)
if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem()) == 0)
{
return false;
}

View File

@ -1,5 +1,6 @@
#include "Logger.h"
#include "OSSupport/File.h"

View File

@ -22,7 +22,7 @@ cMapManager::cMapManager(cWorld * a_World)
bool cMapManager::DoWithMap(int a_ID, cMapCallback & a_Callback)
bool cMapManager::DoWithMap(UInt32 a_ID, cMapCallback & a_Callback)
{
cCSLock Lock(m_CS);
cMap * Map = GetMapData(a_ID);

View File

@ -32,8 +32,7 @@ public:
cMapManager(cWorld * a_World);
/** Returns the map with the specified ID, nullptr if out of range.
WARNING: The returned map object is not thread safe.
*/
WARNING: The returned map object is not thread safe. */
cMap * GetMapData(unsigned int a_ID);
/** Creates a new map. Returns nullptr on error */
@ -41,13 +40,11 @@ public:
/** Calls the callback for the map with the specified ID.
Returns true if the map was found and the callback called, false if map not found.
Callback return value is ignored.
*/
bool DoWithMap(int a_ID, cMapCallback & a_Callback); // Exported in ManualBindings.cpp
Callback return value is ignored. */
bool DoWithMap(UInt32 a_ID, cMapCallback & a_Callback); // Exported in ManualBindings.cpp
/** Calls the callback for each map.
Returns true if all maps processed, false if the callback aborted by returning true.
*/
Returns true if all maps processed, false if the callback aborted by returning true. */
bool ForEachMap(cMapCallback & a_Callback);
size_t GetNumMaps(void) const; // tolua_export

View File

@ -67,30 +67,29 @@ void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
}
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER);
if ((a_Killer != nullptr) && a_Killer->IsProjectile() && (((cProjectileEntity *)a_Killer)->GetCreatorUniqueID() >= 0))
// If the creeper was killed by a skeleton, add a random music disc drop:
if (
(a_Killer != nullptr) &&
a_Killer->IsProjectile() &&
((reinterpret_cast<cProjectileEntity *>(a_Killer))->GetCreatorUniqueID() != cEntity::INVALID_ID))
{
class cProjectileCreatorCallback : public cEntityCallback
{
public:
cProjectileCreatorCallback(void)
{
}
cProjectileCreatorCallback(void) {}
virtual bool Item(cEntity * a_Entity) override
{
if (a_Entity->IsMob() && ((cMonster *)a_Entity)->GetMobType() == mtSkeleton)
if (a_Entity->IsMob() && ((reinterpret_cast<cMonster *>(a_Entity))->GetMobType() == mtSkeleton))
{
return true;
}
return false;
}
};
cProjectileCreatorCallback PCC;
if (GetWorld()->DoWithEntityByID(((cProjectileEntity *)a_Killer)->GetCreatorUniqueID(), PCC))
} PCC;
if (GetWorld()->DoWithEntityByID((reinterpret_cast<cProjectileEntity *>(a_Killer))->GetCreatorUniqueID(), PCC))
{
// 12 music discs. TickRand starts from 0 to 11. Disk IDs start at 2256, so add that. There.
AddRandomDropItem(a_Drops, 1, 1, (short)m_World->GetTickRandomNumber(11) + 2256);
AddRandomDropItem(a_Drops, 1, 1, static_cast<short>(m_World->GetTickRandomNumber(11) + E_ITEM_FIRST_DISC));
}
}
}

View File

@ -10,22 +10,22 @@
class cCriticalSection
{
public:
void Lock(void);
void Unlock(void);
// IsLocked/IsLockedByCurrentThread are only used in ASSERT statements, but because of the changes with ASSERT they must always be defined
// The fake versions (in Release) will not effect the program in any way
#ifdef _DEBUG
cCriticalSection(void);
bool IsLocked(void);
bool IsLockedByCurrentThread(void);
cCriticalSection(void);
bool IsLocked(void);
bool IsLockedByCurrentThread(void);
#else
bool IsLocked(void) { return false; }
bool IsLockedByCurrentThread(void) { return false; }
bool IsLocked(void) { return false; }
bool IsLockedByCurrentThread(void) { return false; }
#endif // _DEBUG
private:
#ifdef _DEBUG
int m_IsLocked; // Number of times this CS is locked
std::thread::id m_OwningThreadID;

View File

@ -8,19 +8,23 @@ SET (SRCS
Authenticator.cpp
ChunkDataSerializer.cpp
MojangAPI.cpp
Packetizer.cpp
Protocol17x.cpp
Protocol18x.cpp
ProtocolRecognizer.cpp)
ProtocolRecognizer.cpp
)
SET (HDRS
Authenticator.h
ChunkDataSerializer.h
MojangAPI.h
Packetizer.h
Protocol.h
Protocol17x.h
Protocol18x.h
ProtocolRecognizer.h)
ProtocolRecognizer.h
)
if(NOT MSVC)
if (NOT MSVC)
add_library(Protocol ${SRCS} ${HDRS})
endif()

View File

@ -187,11 +187,11 @@ void cChunkDataSerializer::Serialize47(AString & a_Data, int a_ChunkX, int a_Chu
// Create the packet:
cByteBuffer Packet(512 KiB);
Packet.WriteVarInt(0x21); // Packet id (Chunk Data packet)
Packet.WriteBEInt(a_ChunkX);
Packet.WriteBEInt(a_ChunkZ);
Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag
Packet.WriteBEUShort(0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff
Packet.WriteVarInt32(0x21); // Packet id (Chunk Data packet)
Packet.WriteBEInt32(a_ChunkX);
Packet.WriteBEInt32(a_ChunkZ);
Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag
Packet.WriteBEUInt16(0xffff); // We're aways sending the full chunk with no additional data, so the bitmap is 0xffff
// Write the chunk size:
const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width;
@ -201,15 +201,15 @@ void cChunkDataSerializer::Serialize47(AString & a_Data, int a_ChunkX, int a_Chu
sizeof(m_BlockSkyLight) + // Block sky light
BiomeDataSize // Biome data
);
Packet.WriteVarInt(ChunkSize);
Packet.WriteVarInt32(ChunkSize);
// Write the block types to the packet:
for (size_t Index = 0; Index < cChunkDef::NumBlocks; Index++)
{
BLOCKTYPE BlockType = m_BlockTypes[Index] & 0xFF;
NIBBLETYPE BlockMeta = m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0x0f;
Packet.WriteByte((unsigned char)(BlockType << 4) | BlockMeta);
Packet.WriteByte((unsigned char)(BlockType >> 4));
Packet.WriteBEUInt8(static_cast<unsigned char>(BlockType << 4) | BlockMeta);
Packet.WriteBEUInt8(static_cast<unsigned char>(BlockType >> 4));
}
// Write the rest:
@ -234,8 +234,8 @@ void cChunkDataSerializer::Serialize47(AString & a_Data, int a_ChunkX, int a_Chu
else
{
AString PostData;
Buffer.WriteVarInt((UInt32)Packet.GetUsedSpace() + 1);
Buffer.WriteVarInt(0);
Buffer.WriteVarInt32(static_cast<UInt32>(Packet.GetUsedSpace() + 1));
Buffer.WriteVarInt32(0);
Buffer.ReadAll(PostData);
Buffer.CommitRead();

101
src/Protocol/Packetizer.cpp Normal file
View File

@ -0,0 +1,101 @@
// Packetizer.cpp
// Implements the cPacketizer class representing a wrapper for sending a single packet over a protocol.
#include "Globals.h"
#include "Packetizer.h"
/** Converts the hex digit character to its value. */
static UInt8 HexDigitValue(char a_Character)
{
switch (a_Character)
{
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case 'a': return 10;
case 'b': return 11;
case 'c': return 12;
case 'd': return 13;
case 'e': return 14;
case 'f': return 15;
case 'A': return 10;
case 'B': return 11;
case 'C': return 12;
case 'D': return 13;
case 'E': return 14;
case 'F': return 15;
default:
{
LOGWARNING("Bad hex digit: %c", a_Character);
ASSERT(!"Bad hex digit");
return 0;
}
}
}
////////////////////////////////////////////////////////////////////////////////
// cPacketizer:
cPacketizer::~cPacketizer()
{
m_Protocol.SendPacket(*this);
}
void cPacketizer::WriteByteAngle(double a_Angle)
{
WriteBEInt8(static_cast<Int8>(255 * a_Angle / 360));
}
void cPacketizer::WriteFPInt(double a_Value)
{
WriteBEInt32(static_cast<Int32>(a_Value * 32));
}
void cPacketizer::WriteUUID(const AString & a_UUID)
{
if (a_UUID.length() != 32)
{
LOGWARNING("%s: Attempt to send a bad uuid (length isn't 32): %s", __FUNCTION__, a_UUID.c_str());
ASSERT(!"Wrong uuid length!");
return;
}
for (size_t i = 0; i < 32; i += 2)
{
auto val = static_cast<UInt8>(HexDigitValue(a_UUID[i]) << 4 | HexDigitValue(a_UUID[i + 1]));
VERIFY(m_Out.WriteBEUInt8(val));
}
}

155
src/Protocol/Packetizer.h Normal file
View File

@ -0,0 +1,155 @@
// Packetizer.h
// Declares the cPacketizer class representing a wrapper for sending a single packet over a protocol.
// The class provides auto-locking, serialization and send-on-instance-destroy semantics
#pragma once
#include "Protocol.h"
#include "../ByteBuffer.h"
/** Composes an individual packet in the protocol's m_OutPacketBuffer; sends it just before being destructed. */
class cPacketizer
{
public:
/** Starts serializing a new packet into the protocol's m_OutPacketBuffer.
Locks the protocol's m_CSPacket to avoid multithreading issues. */
cPacketizer(cProtocol & a_Protocol, UInt32 a_PacketType) :
m_Protocol(a_Protocol),
m_Out(a_Protocol.m_OutPacketBuffer),
m_Lock(a_Protocol.m_CSPacket),
m_PacketType(a_PacketType) // Used for logging purposes
{
m_Out.WriteVarInt32(a_PacketType);
}
/** Sends the packet via the contained protocol's SendPacket() function. */
~cPacketizer();
inline void WriteBool(bool a_Value)
{
VERIFY(m_Out.WriteBool(a_Value));
}
inline void WriteBEUInt8(UInt8 a_Value)
{
VERIFY(m_Out.WriteBEUInt8(a_Value));
}
inline void WriteBEInt8(Int8 a_Value)
{
VERIFY(m_Out.WriteBEInt8(a_Value));
}
inline void WriteBEInt16(Int16 a_Value)
{
VERIFY(m_Out.WriteBEInt16(a_Value));
}
inline void WriteBEUInt16(short a_Value)
{
VERIFY(m_Out.WriteBEUInt16(a_Value));
}
inline void WriteBEInt32(Int32 a_Value)
{
VERIFY(m_Out.WriteBEInt32(a_Value));
}
inline void WriteBEUInt32(UInt32 a_Value)
{
VERIFY(m_Out.WriteBEUInt32(a_Value));
}
inline void WriteBEInt64(Int64 a_Value)
{
VERIFY(m_Out.WriteBEInt64(a_Value));
}
inline void WriteBEUInt64(UInt64 a_Value)
{
VERIFY(m_Out.WriteBEUInt64(a_Value));
}
inline void WriteBEFloat(float a_Value)
{
VERIFY(m_Out.WriteBEFloat(a_Value));
}
inline void WriteBEDouble(double a_Value)
{
VERIFY(m_Out.WriteBEDouble(a_Value));
}
inline void WriteVarInt32(UInt32 a_Value)
{
VERIFY(m_Out.WriteVarInt32(a_Value));
}
inline void WriteString(const AString & a_Value)
{
VERIFY(m_Out.WriteVarUTF8String(a_Value));
}
inline void WriteBuf(const char * a_Data, size_t a_Size)
{
VERIFY(m_Out.Write(a_Data, a_Size));
}
/** Writes the specified block position as a single encoded 64-bit BigEndian integer. */
inline void WritePosition64(int a_BlockX, int a_BlockY, int a_BlockZ)
{
VERIFY(m_Out.WritePosition64(a_BlockX, a_BlockY, a_BlockZ));
}
/** Writes the specified angle using a single byte. */
void WriteByteAngle(double a_Angle);
/** Writes the double value as a 27:5 fixed-point integer. */
void WriteFPInt(double a_Value);
/** Writes the specified UUID as a 128-bit BigEndian integer. */
void WriteUUID(const AString & a_UUID);
UInt32 GetPacketType(void) const { return m_PacketType; }
protected:
/** The protocol instance in which the packet is being constructed. */
cProtocol & m_Protocol;
/** The protocol's buffer for the constructed packet data. */
cByteBuffer & m_Out;
/** The RAII lock preventing multithreaded access to the protocol buffer while constructing the packet. */
cCSLock m_Lock;
/** Type of the contained packet.
Used for logging purposes, the packet type is encoded into m_Out immediately in constructor. */
UInt32 m_PacketType;
} ;

View File

@ -14,6 +14,7 @@
#include "../Endianness.h"
#include "../Scoreboard.h"
#include "../Map.h"
#include "../ByteBuffer.h"
@ -32,6 +33,7 @@ class cChunkDataSerializer;
class cFallingBlock;
class cCompositeChat;
class cStatManager;
class cPacketizer;
@ -47,7 +49,9 @@ class cProtocol
{
public:
cProtocol(cClientHandle * a_Client) :
m_Client(a_Client)
m_Client(a_Client),
m_OutPacketBuffer(64 KiB),
m_OutPacketLenBuffer(20) // 20 bytes is more than enough for one VarInt
{
}
@ -59,7 +63,7 @@ public:
// Sending stuff to clients (alphabetically sorted):
virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) = 0;
virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) = 0;
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) = 0;
virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) = 0;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0;
virtual void SendChat (const AString & a_Message) = 0;
@ -136,11 +140,27 @@ public:
virtual AString GetAuthServerID(void) = 0;
protected:
cClientHandle * m_Client;
cCriticalSection m_CSPacket; // Each SendXYZ() function must acquire this CS in order to send the whole packet at once
friend class cPacketizer;
/// A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it
cClientHandle * m_Client;
/** Provides synchronization for sending the entire packet at once.
Each SendXYZ() function must acquire this CS in order to send the whole packet at once.
Automated via cPacketizer class. */
cCriticalSection m_CSPacket;
/** Buffer for composing the outgoing packets, through cPacketizer */
cByteBuffer m_OutPacketBuffer;
/** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */
cByteBuffer m_OutPacketLenBuffer;
/** A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it. */
virtual void SendData(const char * a_Data, size_t a_Size) = 0;
/** Sends a single packet contained within the cPacketizer class.
The cPacketizer's destructor calls this to send the contained packet; protocol may transform the data (compression in 1.8 etc). */
virtual void SendPacket(cPacketizer & a_Packet) = 0;
} ;

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,7 @@ public:
/** Sending stuff to clients (alphabetically sorted): */
virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override;
virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
@ -140,89 +140,6 @@ public:
protected:
/** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */
class cPacketizer
{
public:
cPacketizer(cProtocol172 & a_Protocol, UInt32 a_PacketType) :
m_Protocol(a_Protocol),
m_Out(a_Protocol.m_OutPacketBuffer),
m_Lock(a_Protocol.m_CSPacket)
{
m_Out.WriteVarInt(a_PacketType);
}
~cPacketizer();
void WriteBool(bool a_Value)
{
m_Out.WriteBool(a_Value);
}
void WriteByte(Byte a_Value)
{
m_Out.WriteByte(a_Value);
}
void WriteChar(char a_Value)
{
m_Out.WriteChar(a_Value);
}
void WriteShort(short a_Value)
{
m_Out.WriteBEShort(a_Value);
}
void WriteInt(int a_Value)
{
m_Out.WriteBEInt(a_Value);
}
void WriteInt64(Int64 a_Value)
{
m_Out.WriteBEInt64(a_Value);
}
void WriteFloat(float a_Value)
{
m_Out.WriteBEFloat(a_Value);
}
void WriteDouble(double a_Value)
{
m_Out.WriteBEDouble(a_Value);
}
void WriteVarInt(UInt32 a_Value)
{
m_Out.WriteVarInt(a_Value);
}
void WriteString(const AString & a_Value)
{
m_Out.WriteVarUTF8String(a_Value);
}
void WriteBuf(const char * a_Data, size_t a_Size)
{
m_Out.Write(a_Data, a_Size);
}
void WriteItem(const cItem & a_Item);
void WriteByteAngle(double a_Angle); // Writes the specified angle using a single byte
void WriteFPInt(double a_Value); // Writes the double value as a 27:5 fixed-point integer
void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f
void WriteMobMetadata(const cMonster & a_Mob); // Writes the mob-specific metadata for the specified mob
void WriteEntityProperties(const cEntity & a_Entity); // Writes the entity properties for the specified entity, including the Count field
void WriteBlockEntity(const cBlockEntity & a_BlockEntity);
protected:
cProtocol172 & m_Protocol;
cByteBuffer & m_Out;
cCSLock m_Lock;
} ;
AString m_ServerAddress;
UInt16 m_ServerPort;
@ -235,12 +152,6 @@ protected:
/** Buffer for the received data */
cByteBuffer m_ReceivedData;
/** Buffer for composing the outgoing packets, through cPacketizer */
cByteBuffer m_OutPacketBuffer;
/** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */
cByteBuffer m_OutPacketLenBuffer;
bool m_IsEncrypted;
cAesCfb128Decryptor m_Decryptor;
@ -297,11 +208,14 @@ protected:
/** Parses Vanilla plugin messages into specific ClientHandle calls.
The message payload is still in the bytebuffer, to be read by this function. */
void HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const AString & a_Channel, short a_PayloadLength);
void HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const AString & a_Channel, UInt16 a_PayloadLength);
/** Sends the data to the client, encrypting them if needed. */
virtual void SendData(const char * a_Data, size_t a_Size) override;
/** Sends the packet to the client. Called by the cPacketizer's destructor. */
virtual void SendPacket(cPacketizer & a_Packet) override;
void SendCompass(const cWorld & a_World);
/** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data */
@ -312,6 +226,24 @@ protected:
void StartEncryption(const Byte * a_Key);
/** Converts the BlockFace received by the protocol into eBlockFace constants.
If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */
eBlockFace FaceIntToBlockFace(Int8 a_FaceInt);
/** Writes the item data into a packet. */
void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item);
/** Writes the metadata for the specified entity, not including the terminating 0x7f. */
void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity);
/** Writes the mob-specific metadata for the specified mob */
void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob);
/** Writes the entity properties for the specified entity, including the Count field. */
void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity);
/** Writes the block entity data for the specified block entity into the packet. */
void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity);
} ;

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@ public:
/** Sending stuff to clients (alphabetically sorted): */
virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override;
virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
@ -150,96 +150,6 @@ public:
protected:
/** Composes individual packets in the protocol's m_OutPacketBuffer; sends them upon being destructed */
class cPacketizer
{
public:
cPacketizer(cProtocol180 & a_Protocol, UInt32 a_PacketType) :
m_Protocol(a_Protocol),
m_Out(a_Protocol.m_OutPacketBuffer),
m_Lock(a_Protocol.m_CSPacket)
{
m_Out.WriteVarInt(a_PacketType);
}
~cPacketizer();
void WriteBool(bool a_Value)
{
m_Out.WriteBool(a_Value);
}
void WriteByte(Byte a_Value)
{
m_Out.WriteByte(a_Value);
}
void WriteChar(char a_Value)
{
m_Out.WriteChar(a_Value);
}
void WriteShort(short a_Value)
{
m_Out.WriteBEShort(a_Value);
}
void WriteInt(int a_Value)
{
m_Out.WriteBEInt(a_Value);
}
void WriteInt64(Int64 a_Value)
{
m_Out.WriteBEInt64(a_Value);
}
void WriteFloat(float a_Value)
{
m_Out.WriteBEFloat(a_Value);
}
void WriteDouble(double a_Value)
{
m_Out.WriteBEDouble(a_Value);
}
void WriteVarInt(UInt32 a_Value)
{
m_Out.WriteVarInt(a_Value);
}
void WriteString(const AString & a_Value)
{
m_Out.WriteVarUTF8String(a_Value);
}
void WritePosition(int a_BlockX, int a_BlockY, int a_BlockZ)
{
m_Out.WritePosition(a_BlockX, a_BlockY, a_BlockZ);
}
void WriteUUID(const AString & a_UUID);
void WriteBuf(const char * a_Data, size_t a_Size)
{
m_Out.Write(a_Data, a_Size);
}
void WriteItem(const cItem & a_Item);
void WriteByteAngle(double a_Angle); // Writes the specified angle using a single byte
void WriteFPInt(double a_Value); // Writes the double value as a 27:5 fixed-point integer
void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f
void WriteMobMetadata(const cMonster & a_Mob); // Writes the mob-specific metadata for the specified mob
void WriteEntityProperties(const cEntity & a_Entity); // Writes the entity properties for the specified entity, including the Count field
void WriteBlockEntity(const cBlockEntity & a_BlockEntity);
protected:
cProtocol180 & m_Protocol;
cByteBuffer & m_Out;
cCSLock m_Lock;
} ;
AString m_ServerAddress;
UInt16 m_ServerPort;
@ -252,12 +162,6 @@ protected:
/** Buffer for the received data */
cByteBuffer m_ReceivedData;
/** Buffer for composing the outgoing packets, through cPacketizer */
cByteBuffer m_OutPacketBuffer;
/** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */
cByteBuffer m_OutPacketLenBuffer;
bool m_IsEncrypted;
cAesCfb128Decryptor m_Decryptor;
@ -320,6 +224,9 @@ protected:
/** Sends the data to the client, encrypting them if needed. */
virtual void SendData(const char * a_Data, size_t a_Size) override;
/** Sends the packet to the client. Called by the cPacketizer's destructor. */
virtual void SendPacket(cPacketizer & a_Packet) override;
void SendCompass(const cWorld & a_World);
/** Reads an item out of the received data, sets a_Item to the values read.
@ -332,6 +239,24 @@ protected:
void StartEncryption(const Byte * a_Key);
/** Converts the BlockFace received by the protocol into eBlockFace constants.
If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */
eBlockFace FaceIntToBlockFace(Int8 a_FaceInt);
/** Writes the item data into a packet. */
void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item);
/** Writes the metadata for the specified entity, not including the terminating 0x7f. */
void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity);
/** Writes the mob-specific metadata for the specified mob */
void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob);
/** Writes the entity properties for the specified entity, including the Count field. */
void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity);
/** Writes the block entity data for the specified block entity into the packet. */
void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity);
} ;

View File

@ -108,10 +108,10 @@ void cProtocolRecognizer::SendBlockAction(int a_BlockX, int a_BlockY, int a_Bloc
void cProtocolRecognizer::SendBlockBreakAnim(int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage)
void cProtocolRecognizer::SendBlockBreakAnim(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage)
{
ASSERT(m_Protocol != nullptr);
m_Protocol->SendBlockBreakAnim(a_entityID, a_BlockX, a_BlockY, a_BlockZ, stage);
m_Protocol->SendBlockBreakAnim(a_EntityID, a_BlockX, a_BlockY, a_BlockZ, a_Stage);
}
@ -911,13 +911,13 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
case PROTO_VERSION_1_7_2:
{
AString ServerAddress;
short ServerPort;
UInt16 ServerPort;
UInt32 NextState;
if (!m_Buffer.ReadVarUTF8String(ServerAddress))
{
break;
}
if (!m_Buffer.ReadBEShort(ServerPort))
if (!m_Buffer.ReadBEUInt16(ServerPort))
{
break;
}
@ -926,19 +926,19 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
break;
}
m_Buffer.CommitRead();
m_Protocol = new cProtocol172(m_Client, ServerAddress, (UInt16)ServerPort, NextState);
m_Protocol = new cProtocol172(m_Client, ServerAddress, ServerPort, NextState);
return true;
}
case PROTO_VERSION_1_7_6:
{
AString ServerAddress;
short ServerPort;
UInt16 ServerPort;
UInt32 NextState;
if (!m_Buffer.ReadVarUTF8String(ServerAddress))
{
break;
}
if (!m_Buffer.ReadBEShort(ServerPort))
if (!m_Buffer.ReadBEUInt16(ServerPort))
{
break;
}
@ -947,19 +947,19 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
break;
}
m_Buffer.CommitRead();
m_Protocol = new cProtocol176(m_Client, ServerAddress, (UInt16)ServerPort, NextState);
m_Protocol = new cProtocol176(m_Client, ServerAddress, ServerPort, NextState);
return true;
}
case PROTO_VERSION_1_8_0:
{
AString ServerAddress;
short ServerPort;
UInt16 ServerPort;
UInt32 NextState;
if (!m_Buffer.ReadVarUTF8String(ServerAddress))
{
break;
}
if (!m_Buffer.ReadBEShort(ServerPort))
if (!m_Buffer.ReadBEUInt16(ServerPort))
{
break;
}
@ -968,12 +968,12 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
break;
}
m_Buffer.CommitRead();
m_Protocol = new cProtocol180(m_Client, ServerAddress, (UInt16)ServerPort, NextState);
m_Protocol = new cProtocol180(m_Client, ServerAddress, ServerPort, NextState);
return true;
}
}
LOGINFO("Client \"%s\" uses an unsupported protocol (lengthed, version %u)",
m_Client->GetIPString().c_str(), ProtocolVersion
LOGINFO("Client \"%s\" uses an unsupported protocol (lengthed, version %u (0x%x))",
m_Client->GetIPString().c_str(), ProtocolVersion, ProtocolVersion
);
m_Client->Kick("Unsupported protocol version");
return false;
@ -982,3 +982,15 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
void cProtocolRecognizer::SendPacket(cPacketizer & a_Pkt)
{
// This function should never be called - it needs to exists so that cProtocolRecognizer can be instantiated,
// but the actual sending is done by the internal m_Protocol itself.
LOGWARNING("%s: This function shouldn't ever be called.", __FUNCTION__);
ASSERT(!"Function not to be called");
}

View File

@ -50,7 +50,7 @@ public:
/// Sending stuff to clients (alphabetically sorted):
virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override;
virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
@ -136,9 +136,12 @@ protected:
/** Tries to recognize a protocol in the lengthed family (1.7+), based on m_Buffer; returns true if recognized.
The packet length and type have already been read, type is 0
The number of bytes remaining in the packet is passed as a_PacketLengthRemaining
**/
The number of bytes remaining in the packet is passed as a_PacketLengthRemaining. **/
bool TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRemaining);
/** Sends a single packet contained within the cPacketizer class.
The cPacketizer's destructor calls this to send the contained packet; protocol may transform the data (compression in 1.8 etc). */
virtual void SendPacket(cPacketizer & a_Pkt) override;
} ;

View File

@ -248,28 +248,31 @@ public:
protected:
/// Maps player's EntityID -> current recipe; not a std::map because cCraftingGrid needs proper constructor params
typedef std::list<std::pair<int, cCraftingRecipe> > cRecipeMap;
/** Maps player's EntityID -> current recipe.
Not a std::map because cCraftingGrid needs proper constructor params. */
typedef std::list<std::pair<UInt32, cCraftingRecipe> > cRecipeMap;
int m_GridSize;
cRecipeMap m_Recipes;
/// Handles a click in the result slot. Crafts using the current recipe, if possible
/** Handles a click in the result slot.
Crafts using the current recipe, if possible. */
void ClickedResult(cPlayer & a_Player);
/// Handles a shift-click in the result slot. Crafts using the current recipe until it changes or no more space for result.
/** Handles a shift-click in the result slot.
Crafts using the current recipe until it changes or no more space for result. */
void ShiftClickedResult(cPlayer & a_Player);
/** Handles a drop-click in the result slot. */
void DropClickedResult(cPlayer & a_Player);
/// Updates the current recipe and result slot based on the ingredients currently in the crafting grid of the specified player
/** Updates the current recipe and result slot based on the ingredients currently in the crafting grid of the specified player. */
void UpdateRecipe(cPlayer & a_Player);
/// Retrieves the recipe for the specified player from the map, or creates one if not found
/** Retrieves the recipe for the specified player from the map, or creates one if not found. */
cCraftingRecipe & GetRecipeForPlayer(cPlayer & a_Player);
/// Called after an item has been crafted to handle statistics e.t.c.
/** Called after an item has been crafted to handle statistics e.t.c. */
void HandleCraftItem(const cItem & a_Result, cPlayer & a_Player);
} ;

View File

@ -1920,7 +1920,7 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
int cWorld::SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NIBBLETYPE BlockMeta)
UInt32 cWorld::SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NIBBLETYPE BlockMeta)
{
cFallingBlock * FallingBlock = new cFallingBlock(Vector3i(a_X, a_Y, a_Z), BlockType, BlockMeta);
FallingBlock->Initialize(*this);
@ -1931,11 +1931,12 @@ int cWorld::SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NI
int cWorld::SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward)
UInt32 cWorld::SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward)
{
if (a_Reward < 1)
{
return -1;
LOGWARNING("%s: Attempting to create an experience orb with non-positive reward!", __FUNCTION__);
return cEntity::INVALID_ID;
}
cExpOrb * ExpOrb = new cExpOrb(a_X, a_Y, a_Z, a_Reward);
@ -1947,7 +1948,7 @@ int cWorld::SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward)
int cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType, const cItem & a_Content, int a_BlockHeight)
UInt32 cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType, const cItem & a_Content, int a_BlockHeight)
{
cMinecart * Minecart;
switch (a_MinecartType)
@ -1959,7 +1960,7 @@ int cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType
case E_ITEM_MINECART_WITH_HOPPER: Minecart = new cMinecartWithHopper (a_X, a_Y, a_Z); break;
default:
{
return -1;
return cEntity::INVALID_ID;
}
} // switch (a_MinecartType)
Minecart->Initialize(*this);
@ -1970,7 +1971,7 @@ int cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType
void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTicks, double a_InitialVelocityCoeff)
UInt32 cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTicks, double a_InitialVelocityCoeff)
{
cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTicks);
TNT->Initialize(*this);
@ -1979,6 +1980,7 @@ void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTicks,
a_InitialVelocityCoeff * 2,
a_InitialVelocityCoeff * (GetTickRandomNumber(2) - 1)
);
return TNT->GetUniqueID();
}
@ -2069,7 +2071,7 @@ void cWorld::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char
void cWorld::BroadcastBlockBreakAnimation(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude)
void cWorld::BroadcastBlockBreakAnimation(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude)
{
m_ChunkMap->BroadcastBlockBreakAnimation(a_EntityID, a_BlockX, a_BlockY, a_BlockZ, a_Stage, a_Exclude);
}
@ -2906,7 +2908,7 @@ bool cWorld::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_
bool cWorld::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback)
bool cWorld::DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback & a_Callback)
{
// First check the entities-to-add:
{
@ -3215,7 +3217,7 @@ void cWorld::AddEntity(cEntity * a_Entity)
bool cWorld::HasEntity(int a_UniqueID)
bool cWorld::HasEntity(UInt32 a_UniqueID)
{
// Check if the entity is in the queue to be added to the world:
{
@ -3332,15 +3334,16 @@ bool cWorld::IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ)
int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType)
UInt32 cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType)
{
cMonster * Monster = nullptr;
Monster = cMonster::NewMonsterFromType(a_MonsterType);
if (Monster != nullptr)
if (Monster == nullptr)
{
Monster->SetPosition(a_PosX, a_PosY, a_PosZ);
return cEntity::INVALID_ID;
}
Monster->SetPosition(a_PosX, a_PosY, a_PosZ);
return SpawnMobFinalize(Monster);
}
@ -3348,13 +3351,9 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a
int cWorld::SpawnMobFinalize(cMonster * a_Monster)
UInt32 cWorld::SpawnMobFinalize(cMonster * a_Monster)
{
// Invalid cMonster object. Bail out.
if (!a_Monster)
{
return -1;
}
ASSERT(a_Monster != nullptr);
// Give the mob full health.
a_Monster->SetHealth(a_Monster->GetMaxHealth());
@ -3364,7 +3363,7 @@ int cWorld::SpawnMobFinalize(cMonster * a_Monster)
{
delete a_Monster;
a_Monster = nullptr;
return -1;
return cEntity::INVALID_ID;
}
// Initialize the monster into the current world.
@ -3372,7 +3371,7 @@ int cWorld::SpawnMobFinalize(cMonster * a_Monster)
{
delete a_Monster;
a_Monster = nullptr;
return -1;
return cEntity::INVALID_ID;
}
cPluginManager::Get()->CallHookSpawnedMonster(*this, *a_Monster);
@ -3384,18 +3383,18 @@ int cWorld::SpawnMobFinalize(cMonster * a_Monster)
int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed)
UInt32 cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed)
{
cProjectileEntity * Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_PosX, a_PosY, a_PosZ, a_Item, a_Speed);
if (Projectile == nullptr)
{
return -1;
return cEntity::INVALID_ID;
}
if (!Projectile->Initialize(*this))
{
delete Projectile;
Projectile = nullptr;
return -1;
return cEntity::INVALID_ID;
}
return Projectile->GetUniqueID();
}

View File

@ -216,7 +216,7 @@ public:
// (Please keep these alpha-sorted)
void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
void BroadcastBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr); // tolua_export
void BroadcastBlockBreakAnimation(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = nullptr);
void BroadcastBlockBreakAnimation(UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = nullptr);
void BroadcastBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = nullptr); ///< If there is a block entity at the specified coods, sends it to all clients except a_Exclude
// tolua_begin
@ -336,7 +336,9 @@ public:
The entity is added lazily - this function only puts it in a queue that is then processed by the Tick thread. */
void AddEntity(cEntity * a_Entity);
bool HasEntity(int a_UniqueID);
/** Returns true if an entity with the specified UniqueID exists in the world.
Note: Only loaded chunks are considered. */
bool HasEntity(UInt32 a_UniqueID);
/** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
@ -349,8 +351,9 @@ public:
If any chunk in the box is missing, ignores the entities in that chunk silently. */
bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. */
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param.
Returns true if entity found and callback returned false. */
bool DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
/** Compares clients of two chunks, calls the callback accordingly */
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
@ -477,20 +480,25 @@ public:
/** Spawns item pickups for each item in the list. May compress pickups if too many entities: */
virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false) override;
/** Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified: */
/** Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified. */
virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false) override;
/** Spawns an falling block entity at the given position. It returns the UniqueID of the spawned falling block. */
int SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NIBBLETYPE BlockMeta);
/** Spawns an falling block entity at the given position.
Returns the UniqueID of the spawned falling block, or cEntity::INVALID_ID on failure. */
UInt32 SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE BlockType, NIBBLETYPE BlockMeta);
/** Spawns an minecart at the given coordinates. */
int SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType, const cItem & a_Content = cItem(), int a_BlockHeight = 1);
/** Spawns an minecart at the given coordinates.
Returns the UniqueID of the spawned minecart, or cEntity::INVALID_ID on failure. */
UInt32 SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType, const cItem & a_Content = cItem(), int a_BlockHeight = 1);
/** Spawns an experience orb at the given location with the given reward. It returns the UniqueID of the spawned experience orb. */
virtual int SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) override;
/** Spawns an experience orb at the given location with the given reward.
Returns the UniqueID of the spawned experience orb, or cEntity::INVALID_ID on failure. */
virtual UInt32 SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) override;
/** Spawns a new primed TNT entity at the specified block coords and specified fuse duration. Initial velocity is given based on the relative coefficient provided */
void SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTimeInSec = 80, double a_InitialVelocityCoeff = 1);
/** Spawns a new primed TNT entity at the specified block coords and specified fuse duration.
Initial velocity is given based on the relative coefficient provided.
Returns the UniqueID of the created entity, or cEntity::INVALID_ID on failure. */
UInt32 SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTimeInSec = 80, double a_InitialVelocityCoeff = 1);
// tolua_end
@ -796,14 +804,14 @@ public:
bool IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
/** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) override; // tolua_export
int SpawnMobFinalize(cMonster* a_Monster);
/** Spawns a mob of the specified type. Returns the mob's UniqueID if recognized and spawned, cEntity::INVALID_ID otherwise */
virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) override; // tolua_export
UInt32 SpawnMobFinalize(cMonster * a_Monster);
/** Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise
Item parameter used currently for Fireworks to correctly set entity metadata based on item metadata
*/
int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed = nullptr); // tolua_export
/** Creates a projectile of the specified type. Returns the projectile's UniqueID if successful, cEntity::INVALID_ID otherwise
Item parameter is currently used for Fireworks to correctly set entity metadata based on item metadata. */
UInt32 CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed = nullptr); // tolua_export
/** Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread! */
int GetTickRandomNumber(int a_Range) { return (int)(m_TickRand.randInt(a_Range)); }