Properly support CPE extension versions > 1

This commit is contained in:
UnknownShadow200 2023-08-11 11:35:03 +10:00
parent 0cba7acede
commit ebb45d00a2

View File

@ -41,12 +41,71 @@ static cc_uint64 map_receiveBeg;
static struct Stream map_part; static struct Stream map_part;
static int map_volume; static int map_volume;
/* CPE state */ /*########################################################################################################################*
*-----------------------------------------------------CPE extensions------------------------------------------------------*
*#########################################################################################################################*/
struct CpeExt {
const char* name;
cc_uint8 clientVersion, serverVersion;
};
cc_bool cpe_needD3Fix; cc_bool cpe_needD3Fix;
static int cpe_serverExtensionsCount, cpe_pingTicks; static int cpe_serverExtensionsCount, cpe_pingTicks;
static int cpe_envMapVer = 2, cpe_blockDefsExtVer = 2, cpe_customModelsVer = 2;
static cc_bool cpe_sendHeldBlock, cpe_useMessageTypes, cpe_extEntityPos, cpe_blockPerms, cpe_fastMap; static struct CpeExt
static cc_bool cpe_twoWayPing, cpe_pluginMessages, cpe_extTextures, cpe_extBlocks; clickDist_Ext = { "ClickDistance", 1 },
customBlocks_Ext = { "CustomBlocks", 1 },
heldBlock_Ext = { "HeldBlock", 1 },
emoteFix_Ext = { "EmoteFix", 1 },
textHotKey_Ext = { "TextHotKey", 1 },
extPlayerList_Ext = { "ExtPlayerList", 2 },
envColors_Ext = { "EnvColors", 1 },
selectionCuboid_Ext = { "SelectionCuboid", 1 },
blockPerms_Ext = { "BlockPermissions", 1 },
changeModel_Ext = { "ChangeModel", 2 },
mapAppearance_Ext = { "EnvMapAppearance", 2 },
weatherType_Ext = { "EnvWeatherType", 1 },
messageTypes_Ext = { "MessageTypes", 1 },
hackControl_Ext = { "HackControl", 1 },
playerClick_Ext = { "PlayerClick", 1 },
fullCP437_Ext = { "FullCP437", 1 },
longerMessages_Ext = { "LongerMessages", 1 },
blockDefs_Ext = { "BlockDefinitions", 1 },
blockDefsExt_Ext = { "BlockDefinitionsExt", 2 },
bulkBlockUpdate_Ext = { "BulkBlockUpdate", 1 },
textColors_Ext = { "TextColors", 1 },
envMapAspect_Ext = { "EnvMapAspect", 1 },
entityProperty_Ext = { "EntityProperty", 1 },
extEntityPos_Ext = { "ExtEntityPositions", 1 },
twoWayPing_Ext = { "TwoWayPing", 1 },
invOrder_Ext = { "InventoryOrder", 1 },
instantMOTD_Ext = { "InstantMOTD", 1 },
fastMap_Ext = { "FastMap", 1 },
setHotbar_Ext = { "SetHotbar", 1 },
setSpawnpoint_Ext = { "SetSpawnpoint", 1 },
velControl_Ext = { "VelocityControl", 1 },
customParticles_Ext = { "CustomParticles", 1 },
customModels_Ext = { "CustomModels", 2 },
pluginMessages_Ext = { "PluginMessages", 1 },
extTeleport_Ext = { "ExtEntityTeleport", 1 },
extTextures_Ext = { "ExtendedTextures", 1 },
extBlocks_Ext = { "ExtendedBlocks", 1 };
static struct CpeExt* cpe_clientExtensions[] = {
&clickDist_Ext, &customBlocks_Ext, &heldBlock_Ext, &emoteFix_Ext, &textHotKey_Ext, &extPlayerList_Ext,
&envColors_Ext, &selectionCuboid_Ext, &blockPerms_Ext, &changeModel_Ext, &mapAppearance_Ext, &weatherType_Ext,
&messageTypes_Ext, &hackControl_Ext, &playerClick_Ext, &fullCP437_Ext, &longerMessages_Ext, &blockDefs_Ext,
&blockDefsExt_Ext, &bulkBlockUpdate_Ext, &textColors_Ext, &envMapAspect_Ext, &entityProperty_Ext, &extEntityPos_Ext,
&twoWayPing_Ext, &invOrder_Ext, &fastMap_Ext, &setHotbar_Ext, &setSpawnpoint_Ext, &velControl_Ext,
&customParticles_Ext, &customModels_Ext, &pluginMessages_Ext, &extTeleport_Ext,
#ifdef EXTENDED_TEXTURES
&extTextures_Ext,
#endif
#ifdef EXTENDED_BLOCKS
&extBlocks_Ext,
#endif
};
#define IsSupported(ext) (ext.serverVersion > 0)
/*########################################################################################################################* /*########################################################################################################################*
*-----------------------------------------------------Common handlers-----------------------------------------------------* *-----------------------------------------------------Common handlers-----------------------------------------------------*
@ -56,7 +115,7 @@ static cc_bool cpe_twoWayPing, cpe_pluginMessages, cpe_extTextures, cpe_extBlock
#define ReadBlock(data, value) value = *data++; #define ReadBlock(data, value) value = *data++;
#else #else
#define ReadBlock(data, value)\ #define ReadBlock(data, value)\
if (cpe_extBlocks) {\ if (IsSupported(extBlocks_Ext)) {\
value = Stream_GetU16_BE(data) % BLOCK_COUNT; data += 2;\ value = Stream_GetU16_BE(data) % BLOCK_COUNT; data += 2;\
} else { value = *data++; } } else { value = *data++; }
#endif #endif
@ -65,7 +124,7 @@ if (cpe_extBlocks) {\
#define WriteBlock(data, value) *data++ = value; #define WriteBlock(data, value) *data++ = value;
#else #else
#define WriteBlock(data, value)\ #define WriteBlock(data, value)\
if (cpe_extBlocks) {\ if (IsSupported(extBlocks_Ext)) {\
Stream_SetU16_BE(data, value); data += 2;\ Stream_SetU16_BE(data, value); data += 2;\
} else { *data++ = (BlockRaw)value; } } else { *data++ = (BlockRaw)value; }
#endif #endif
@ -175,7 +234,7 @@ static void UpdateLocation(EntityID id, struct LocationUpdate* update) {
static void UpdateUserType(struct HacksComp* hacks, cc_uint8 value) { static void UpdateUserType(struct HacksComp* hacks, cc_uint8 value) {
cc_bool isOp = value >= 100 && value <= 127; cc_bool isOp = value >= 100 && value <= 127;
hacks->IsOp = isOp; hacks->IsOp = isOp;
if (cpe_blockPerms) return; if (IsSupported(blockPerms_Ext)) return;
Blocks.CanPlace[BLOCK_BEDROCK] = isOp; Blocks.CanPlace[BLOCK_BEDROCK] = isOp;
Blocks.CanDelete[BLOCK_BEDROCK] = isOp; Blocks.CanDelete[BLOCK_BEDROCK] = isOp;
@ -258,7 +317,7 @@ static void WoM_ParseConfig(struct HttpRequest* item) {
if (Convert_ParseInt(&value, &waterLevel)) { if (Convert_ParseInt(&value, &waterLevel)) {
Env_SetEdgeHeight(waterLevel); Env_SetEdgeHeight(waterLevel);
} }
} else if (String_CaselessEqualsConst(&key, "user.detail") && !cpe_useMessageTypes) { } else if (String_CaselessEqualsConst(&key, "user.detail") && !IsSupported(messageTypes_Ext)) {
Chat_AddOf(&value, MSG_TYPE_STATUS_2); Chat_AddOf(&value, MSG_TYPE_STATUS_2);
} }
} }
@ -407,13 +466,13 @@ static cc_uint8* Classic_WritePosition(cc_uint8* data, Vec3 pos, float yaw, floa
*data++ = OPCODE_ENTITY_TELEPORT; *data++ = OPCODE_ENTITY_TELEPORT;
{ {
payload = cpe_sendHeldBlock ? Inventory_SelectedBlock : ENTITIES_SELF_ID; payload = IsSupported(heldBlock_Ext) ? Inventory_SelectedBlock : ENTITIES_SELF_ID;
WriteBlock(data, payload); WriteBlock(data, payload);
x = (int)(pos.X * 32); x = (int)(pos.X * 32);
y = (int)(pos.Y * 32) + 51; y = (int)(pos.Y * 32) + 51;
z = (int)(pos.Z * 32); z = (int)(pos.Z * 32);
if (cpe_extEntityPos) { if (IsSupported(extEntityPos_Ext)) {
Stream_SetU32_BE(data, x); data += 4; Stream_SetU32_BE(data, x); data += 4;
Stream_SetU32_BE(data, y); data += 4; Stream_SetU32_BE(data, y); data += 4;
Stream_SetU32_BE(data, z); data += 4; Stream_SetU32_BE(data, z); data += 4;
@ -486,7 +545,7 @@ static void Classic_LevelInit(cc_uint8* data) {
if (map_begunLoading) return; if (map_begunLoading) return;
Classic_StartLoading(); Classic_StartLoading();
if (!cpe_fastMap) return; if (!IsSupported(fastMap_Ext)) return;
/* Fast map puts volume in header, and uses raw DEFLATE without GZIP header/footer */ /* Fast map puts volume in header, and uses raw DEFLATE without GZIP header/footer */
map_volume = Stream_GetU32_BE(data); map_volume = Stream_GetU32_BE(data);
@ -515,7 +574,7 @@ static void Classic_LevelDataChunk(cc_uint8* data) {
m = &map1; m = &map1;
#else #else
/* progress byte in original classic, but we ignore it */ /* progress byte in original classic, but we ignore it */
if (cpe_extBlocks && data[1026]) { if (IsSupported(extBlocks_Ext) && data[1026]) {
m = &map2; m = &map2;
} else { } else {
m = &map1; m = &map1;
@ -568,7 +627,9 @@ static void Classic_LevelFinalise(cc_uint8* data) {
#ifdef EXTENDED_BLOCKS #ifdef EXTENDED_BLOCKS
/* defer allocation of second map array if possible */ /* defer allocation of second map array if possible */
if (cpe_extBlocks && map2.blocks) World_SetMapUpper(map2.blocks); if (IsSupported(extBlocks_Ext) && map2.blocks) {
World_SetMapUpper(map2.blocks);
}
map2.blocks = NULL; map2.blocks = NULL;
#endif #endif
World_SetNewMap(map1.blocks, width, height, length); World_SetNewMap(map1.blocks, width, height, length);
@ -662,7 +723,7 @@ static void Classic_Message(cc_uint8* data) {
String_InitArray(text, textBuffer); String_InitArray(text, textBuffer);
/* Original vanilla server uses player ids for type, 255 for server messages (&e prefix) */ /* Original vanilla server uses player ids for type, 255 for server messages (&e prefix) */
if (!cpe_useMessageTypes) { if (!IsSupported(messageTypes_Ext)) {
if (type == 0xFF) String_AppendConst(&text, "&e"); if (type == 0xFF) String_AppendConst(&text, "&e");
type = MSG_TYPE_NORMAL; type = MSG_TYPE_NORMAL;
} }
@ -694,7 +755,7 @@ static void Classic_ReadAbsoluteLocation(cc_uint8* data, EntityID id, cc_uint8 f
int x, y, z; int x, y, z;
cc_uint8 mode; cc_uint8 mode;
if (cpe_extEntityPos) { if (IsSupported(extEntityPos_Ext)) {
x = (int)Stream_GetU32_BE(&data[0]); x = (int)Stream_GetU32_BE(&data[0]);
y = (int)Stream_GetU32_BE(&data[4]); y = (int)Stream_GetU32_BE(&data[4]);
z = (int)Stream_GetU32_BE(&data[8]); z = (int)Stream_GetU32_BE(&data[8]);
@ -765,16 +826,29 @@ static cc_uint8* Classic_Tick(cc_uint8* data) {
/*########################################################################################################################* /*########################################################################################################################*
*------------------------------------------------------CPE protocol-------------------------------------------------------* *------------------------------------------------------CPE protocol-------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static const char* cpe_clientExtensions[] = {
"ClickDistance", "CustomBlocks", "HeldBlock", "EmoteFix", "TextHotKey", "ExtPlayerList", static void CPEExtensions_Reset(void) {
"EnvColors", "SelectionCuboid", "BlockPermissions", "ChangeModel", "EnvMapAppearance", struct CpeExt* ext;
"EnvWeatherType", "MessageTypes", "HackControl", "PlayerClick", "FullCP437", "LongerMessages", int i;
"BlockDefinitions", "BlockDefinitionsExt", "BulkBlockUpdate", "TextColors", "EnvMapAspect",
"EntityProperty", "ExtEntityPositions", "TwoWayPing", "InventoryOrder", "InstantMOTD", "FastMap", "SetHotbar", for (i = 0; i < Array_Elems(cpe_clientExtensions); i++)
"SetSpawnpoint", "VelocityControl", "CustomParticles", "CustomModels", "PluginMessages", "ExtEntityTeleport", {
/* NOTE: These must be placed last for when EXTENDED_TEXTURES or EXTENDED_BLOCKS are not defined */ ext = cpe_clientExtensions[i];
"ExtendedTextures", "ExtendedBlocks" ext->serverVersion = 0;
}; }
}
static struct CpeExt* CPEExtensions_Find(const cc_string* name) {
struct CpeExt* ext;
int i;
for (i = 0; i < Array_Elems(cpe_clientExtensions); i++)
{
ext = cpe_clientExtensions[i];
if (String_CaselessEqualsConst(name, ext->name)) return ext;
}
return NULL;
}
static void CPE_SetMapEnvUrl(cc_uint8* data); static void CPE_SetMapEnvUrl(cc_uint8* data);
#define Ext_Deg2Packed(x) ((int)((x) * 65536.0f / 360.0f)) #define Ext_Deg2Packed(x) ((int)((x) * 65536.0f / 360.0f))
@ -810,8 +884,7 @@ void CPE_SendPlayerClick(int button, cc_bool pressed, cc_uint8 targetId, struct
void CPE_SendPluginMessage(cc_uint8 channel, cc_uint8* data) { void CPE_SendPluginMessage(cc_uint8 channel, cc_uint8* data) {
cc_uint8 buffer[66]; cc_uint8 buffer[66];
if (!IsSupported(pluginMessages_Ext)) return;
if (!cpe_pluginMessages) return;
buffer[0] = OPCODE_PLUGIN_MESSAGE; buffer[0] = OPCODE_PLUGIN_MESSAGE;
{ {
@ -851,19 +924,13 @@ static cc_uint8* CPE_WriteTwoWayPing(cc_uint8* data, cc_bool serverToClient, int
} }
static void CPE_SendCpeExtInfoReply(void) { static void CPE_SendCpeExtInfoReply(void) {
struct CpeExt* ext;
int count = Array_Elems(cpe_clientExtensions); int count = Array_Elems(cpe_clientExtensions);
cc_string name; cc_string name;
int i, ver; int i, ver;
if (cpe_serverExtensionsCount) return; if (cpe_serverExtensionsCount) return;
#ifndef EXTENDED_TEXTURES
count--;
#endif
#ifndef EXTENDED_BLOCKS
count--;
#endif
#ifdef EXTENDED_BLOCKS #ifdef EXTENDED_BLOCKS
if (!Game_AllowCustomBlocks) count -= 3; if (!Game_AllowCustomBlocks) count -= 3;
#else #else
@ -871,14 +938,12 @@ static void CPE_SendCpeExtInfoReply(void) {
#endif #endif
CPE_SendExtInfo(count); CPE_SendExtInfo(count);
for (i = 0; i < Array_Elems(cpe_clientExtensions); i++) { for (i = 0; i < Array_Elems(cpe_clientExtensions); i++)
name = String_FromReadonly(cpe_clientExtensions[i]); {
ver = 1; ext = cpe_clientExtensions[i];
name = String_FromReadonly(ext->name);
if (String_CaselessEqualsConst(&name, "ExtPlayerList")) ver = 2; ver = ext->serverVersion;
if (String_CaselessEqualsConst(&name, "EnvMapAppearance")) ver = cpe_envMapVer; /* Don't reply with version higher than what server supports to workaround some buggy server software */
if (String_CaselessEqualsConst(&name, "BlockDefinitionsExt")) ver = cpe_blockDefsExtVer;
if (String_CaselessEqualsConst(&name, "CustomModels")) ver = cpe_customModelsVer;
if (!Game_AllowCustomBlocks) { if (!Game_AllowCustomBlocks) {
if (String_CaselessEqualsConst(&name, "BlockDefinitionsExt")) continue; if (String_CaselessEqualsConst(&name, "BlockDefinitionsExt")) continue;
@ -887,13 +952,6 @@ static void CPE_SendCpeExtInfoReply(void) {
if (String_CaselessEqualsConst(&name, "ExtendedBlocks")) continue; if (String_CaselessEqualsConst(&name, "ExtendedBlocks")) continue;
#endif #endif
} }
#ifndef EXTENDED_TEXTURES
if (String_CaselessEqualsConst(&name, "ExtendedTextures")) continue;
#endif
#ifndef EXTENDED_BLOCKS
if (String_CaselessEqualsConst(&name, "ExtendedBlocks")) continue;
#endif
CPE_SendExtEntry(&name, ver); CPE_SendExtEntry(&name, ver);
} }
} }
@ -911,67 +969,55 @@ static void CPE_ExtInfo(cc_uint8* data) {
} }
static void CPE_ExtEntry(cc_uint8* data) { static void CPE_ExtEntry(cc_uint8* data) {
cc_string ext = UNSAFE_GetString(data); struct CpeExt* ext;
cc_string name = UNSAFE_GetString(data);
int version = data[67]; int version = data[67];
Platform_Log2("cpe ext: %s, %i", &ext, &version); Platform_Log2("cpe ext: %s, %i", &name, &version);
cpe_serverExtensionsCount--; cpe_serverExtensionsCount--;
CPE_SendCpeExtInfoReply(); CPE_SendCpeExtInfoReply();
ext = CPEExtensions_Find(&name);
if (!ext) return;
ext->serverVersion = min(ext->clientVersion, version);
/* update support state */ /* update support state */
if (String_CaselessEqualsConst(&ext, "HeldBlock")) { if (ext == &extPlayerList_Ext) {
cpe_sendHeldBlock = true;
} else if (String_CaselessEqualsConst(&ext, "MessageTypes")) {
cpe_useMessageTypes = true;
} else if (String_CaselessEqualsConst(&ext, "ExtPlayerList")) {
Server.SupportsExtPlayerList = true; Server.SupportsExtPlayerList = true;
} else if (String_CaselessEqualsConst(&ext, "BlockPermissions")) { } else if (ext == &playerClick_Ext) {
cpe_blockPerms = true;
} else if (String_CaselessEqualsConst(&ext, "PlayerClick")) {
Server.SupportsPlayerClick = true; Server.SupportsPlayerClick = true;
} else if (String_CaselessEqualsConst(&ext, "EnvMapAppearance")) { } else if (ext == &mapAppearance_Ext) {
cpe_envMapVer = version; if (ext->serverVersion == 1) return;
if (version == 1) return;
Protocol.Sizes[OPCODE_ENV_SET_MAP_APPEARANCE] += 4; Protocol.Sizes[OPCODE_ENV_SET_MAP_APPEARANCE] += 4;
} else if (String_CaselessEqualsConst(&ext, "LongerMessages")) { } else if (ext == &longerMessages_Ext) {
Server.SupportsPartialMessages = true; Server.SupportsPartialMessages = true;
} else if (String_CaselessEqualsConst(&ext, "FullCP437")) { } else if (ext == &fullCP437_Ext) {
Server.SupportsFullCP437 = true; Server.SupportsFullCP437 = true;
} else if (String_CaselessEqualsConst(&ext, "BlockDefinitionsExt")) { } else if (ext == &blockDefsExt_Ext) {
cpe_blockDefsExtVer = version; if (ext->serverVersion == 1) return;
if (version == 1) return;
Protocol.Sizes[OPCODE_DEFINE_BLOCK_EXT] += 3; Protocol.Sizes[OPCODE_DEFINE_BLOCK_EXT] += 3;
} else if (String_CaselessEqualsConst(&ext, "ExtEntityPositions")) { } else if (ext == &extEntityPos_Ext) {
Protocol.Sizes[OPCODE_ENTITY_TELEPORT] += 6; Protocol.Sizes[OPCODE_ENTITY_TELEPORT] += 6;
Protocol.Sizes[OPCODE_ADD_ENTITY] += 6; Protocol.Sizes[OPCODE_ADD_ENTITY] += 6;
Protocol.Sizes[OPCODE_EXT_ADD_ENTITY2] += 6; Protocol.Sizes[OPCODE_EXT_ADD_ENTITY2] += 6;
Protocol.Sizes[OPCODE_SET_SPAWNPOINT] += 6; Protocol.Sizes[OPCODE_SET_SPAWNPOINT] += 6;
Protocol.Sizes[OPCODE_ENTITY_TELEPORT_EXT] += 6; Protocol.Sizes[OPCODE_ENTITY_TELEPORT_EXT] += 6;
cpe_extEntityPos = true; } else if (ext == &fastMap_Ext) {
} else if (String_CaselessEqualsConst(&ext, "TwoWayPing")) {
cpe_twoWayPing = true;
} else if (String_CaselessEqualsConst(&ext, "FastMap")) {
Protocol.Sizes[OPCODE_LEVEL_BEGIN] += 4; Protocol.Sizes[OPCODE_LEVEL_BEGIN] += 4;
cpe_fastMap = true; } else if (ext == &customModels_Ext) {
} else if (String_CaselessEqualsConst(&ext, "CustomModels")) { if (ext->serverVersion == 2) {
cpe_customModelsVer = min(2, version);
if (version == 2) {
Protocol.Sizes[OPCODE_DEFINE_MODEL_PART] = 167; Protocol.Sizes[OPCODE_DEFINE_MODEL_PART] = 167;
} }
} else if (String_CaselessEqualsConst(&ext, "PluginMessages")) {
cpe_pluginMessages = true;
} }
#ifdef EXTENDED_TEXTURES #ifdef EXTENDED_TEXTURES
else if (String_CaselessEqualsConst(&ext, "ExtendedTextures")) { else if (ext == &extTextures_Ext) {
Protocol.Sizes[OPCODE_DEFINE_BLOCK] += 3; Protocol.Sizes[OPCODE_DEFINE_BLOCK] += 3;
Protocol.Sizes[OPCODE_DEFINE_BLOCK_EXT] += 6; Protocol.Sizes[OPCODE_DEFINE_BLOCK_EXT] += 6;
cpe_extTextures = true;
} }
#endif #endif
#ifdef EXTENDED_BLOCKS #ifdef EXTENDED_BLOCKS
else if (String_CaselessEqualsConst(&ext, "ExtendedBlocks")) { else if (ext == &extBlocks_Ext) {
if (!Game_AllowCustomBlocks) return; if (!Game_AllowCustomBlocks) return;
cpe_extBlocks = true;
Protocol.Sizes[OPCODE_SET_BLOCK] += 1; Protocol.Sizes[OPCODE_SET_BLOCK] += 1;
Protocol.Sizes[OPCODE_HOLD_THIS] += 1; Protocol.Sizes[OPCODE_HOLD_THIS] += 1;
@ -1140,7 +1186,7 @@ static void CPE_EnvSetMapAppearance(cc_uint8* data) {
Env_SetSidesBlock(data[64]); Env_SetSidesBlock(data[64]);
Env_SetEdgeBlock(data[65]); Env_SetEdgeBlock(data[65]);
Env_SetEdgeHeight((cc_int16)Stream_GetU16_BE(data + 66)); Env_SetEdgeHeight((cc_int16)Stream_GetU16_BE(data + 66));
if (cpe_envMapVer == 1) return; if (mapAppearance_Ext.serverVersion == 1) return;
/* Version 2 */ /* Version 2 */
Env_SetCloudsHeight((cc_int16)Stream_GetU16_BE(data + 68)); Env_SetCloudsHeight((cc_int16)Stream_GetU16_BE(data + 68));
@ -1203,7 +1249,7 @@ static void CPE_BulkBlockUpdate(cc_uint8* data) {
} }
data += BULK_MAX_BLOCKS; data += BULK_MAX_BLOCKS;
if (cpe_extBlocks) { if (IsSupported(extBlocks_Ext)) {
for (i = 0; i < count; i += 4) { for (i = 0; i < count; i += 4) {
cc_uint8 flags = data[i >> 2]; cc_uint8 flags = data[i >> 2];
blocks[i + 0] |= (BlockID)((flags & 0x03) << 8); blocks[i + 0] |= (BlockID)((flags & 0x03) << 8);
@ -1363,7 +1409,7 @@ static void CPE_SetSpawnPoint(cc_uint8* data) {
struct LocalPlayer* p = &LocalPlayer_Instance; struct LocalPlayer* p = &LocalPlayer_Instance;
int x, y, z; int x, y, z;
if (cpe_extEntityPos) { if (IsSupported(extEntityPos_Ext)) {
x = (int)Stream_GetU32_BE(&data[0]); x = (int)Stream_GetU32_BE(&data[0]);
y = (int)Stream_GetU32_BE(&data[4]); y = (int)Stream_GetU32_BE(&data[4]);
z = (int)Stream_GetU32_BE(&data[8]); z = (int)Stream_GetU32_BE(&data[8]);
@ -1522,10 +1568,10 @@ static void CPE_DefineModelPart(cc_uint8* data) {
part->rotation.Y = GetFloat(data + 89); part->rotation.Y = GetFloat(data + 89);
part->rotation.Z = GetFloat(data + 93); part->rotation.Z = GetFloat(data + 93);
if (cpe_customModelsVer == 1) { if (customModels_Ext.serverVersion == 1) {
/* ignore animations */ /* ignore animations */
p.flags = data[102]; p.flags = data[102];
} else if (cpe_customModelsVer == 2) { } else {
p.flags = data[165]; p.flags = data[165];
data += 97; data += 97;
@ -1583,11 +1629,9 @@ static void CPE_ExtEntityTeleport(cc_uint8* data) {
static void CPE_Reset(void) { static void CPE_Reset(void) {
cpe_serverExtensionsCount = 0; cpe_pingTicks = 0; cpe_serverExtensionsCount = 0; cpe_pingTicks = 0;
cpe_sendHeldBlock = false; cpe_useMessageTypes = false; CPEExtensions_Reset();
cpe_envMapVer = 2; cpe_blockDefsExtVer = 2; cpe_customModelsVer = 2; cpe_needD3Fix = false;
cpe_needD3Fix = false; cpe_extEntityPos = false; cpe_twoWayPing = false; Game_UseCPEBlocks = false;
cpe_pluginMessages = false; cpe_extTextures = false; cpe_fastMap = false;
cpe_extBlocks = false; Game_UseCPEBlocks = false; cpe_blockPerms = false;
if (!Game_Version.HasCPE) return; if (!Game_Version.HasCPE) return;
Net_Set(OPCODE_EXT_INFO, CPE_ExtInfo, 67); Net_Set(OPCODE_EXT_INFO, CPE_ExtInfo, 67);
@ -1632,7 +1676,7 @@ static void CPE_Reset(void) {
static cc_uint8* CPE_Tick(cc_uint8* data) { static cc_uint8* CPE_Tick(cc_uint8* data) {
cpe_pingTicks++; cpe_pingTicks++;
if (cpe_pingTicks >= 20 && cpe_twoWayPing) { if (cpe_pingTicks >= 20 && IsSupported(twoWayPing_Ext)) {
data = CPE_WriteTwoWayPing(data, false, Ping_NextPingId()); data = CPE_WriteTwoWayPing(data, false, Ping_NextPingId());
cpe_pingTicks = 0; cpe_pingTicks = 0;
} }
@ -1653,7 +1697,7 @@ static TextureLoc BlockDefs_Tex(cc_uint8** ptr) {
TextureLoc loc; TextureLoc loc;
cc_uint8* data = *ptr; cc_uint8* data = *ptr;
if (!cpe_extTextures) { if (!IsSupported(extTextures_Ext)) {
loc = *data++; loc = *data++;
} else { } else {
loc = Stream_GetU16_BE(data) % ATLAS1D_MAX_ATLASES; data += 2; loc = Stream_GetU16_BE(data) % ATLAS1D_MAX_ATLASES; data += 2;
@ -1743,7 +1787,8 @@ static void BlockDefs_UndefineBlock(cc_uint8* data) {
static void BlockDefs_DefineBlockExt(cc_uint8* data) { static void BlockDefs_DefineBlockExt(cc_uint8* data) {
Vec3 minBB, maxBB; Vec3 minBB, maxBB;
BlockID block = BlockDefs_DefineBlockCommonStart(&data, cpe_blockDefsExtVer >= 2); BlockID block = BlockDefs_DefineBlockCommonStart(&data,
blockDefsExt_Ext.serverVersion >= 2);
minBB.X = (cc_int8)(*data++) / 16.0f; minBB.X = (cc_int8)(*data++) / 16.0f;
minBB.Y = (cc_int8)(*data++) / 16.0f; minBB.Y = (cc_int8)(*data++) / 16.0f;