From 63af2c8da74cbddf5b754fa6ee150c702effadfa Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 5 Sep 2022 20:28:47 -0700 Subject: [PATCH] Add ZLIB for Windows (#768) Added ZLIB for Windows. Packets for character creation are now compressed on windows before sending and ZCompression can now be used on Windows. --- CMakeLists.txt | 1 - CMakePresets.json | 11 ++++++++--- dCommon/CMakeLists.txt | 30 ++++++++++++++++++++++++++++-- dCommon/ZCompression.cpp | 23 ----------------------- dCommon/ZCompression.h | 5 ----- dNet/WorldPackets.cpp | 26 +++++++++++++++++--------- 6 files changed, 53 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a977a64..721140a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,7 +160,6 @@ elseif (UNIX) set(INCLUDED_DIRECTORIES ${INCLUDED_DIRECTORIES} "thirdparty/libbcrypt/include/bcrypt") endif() -include_directories(${ZLIB_INCLUDE_DIRS}) # Add binary directory as an include directory include_directories(${PROJECT_BINARY_DIR}) diff --git a/CMakePresets.json b/CMakePresets.json index 133d6a3c..badb161d 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -115,9 +115,14 @@ "displayName": "CI Tests on windows", "description": "Runs all tests on a windows configuration", "configuration": "RelWithDebInfo", - "execution": { - "jobs": 2 - }, + "execution": { + "jobs": 2 + }, + "filter": { + "exclude": { + "name": "((example)|(minigzip))+" + } + }, "output": { "outputOnFailure": true } diff --git a/dCommon/CMakeLists.txt b/dCommon/CMakeLists.txt index 028eb29f..18fe582c 100644 --- a/dCommon/CMakeLists.txt +++ b/dCommon/CMakeLists.txt @@ -23,5 +23,31 @@ target_link_libraries(dCommon bcrypt) if (UNIX) find_package(ZLIB REQUIRED) - target_link_libraries(dCommon ZLIB::ZLIB) -endif() +elseif (WIN32) + include(FetchContent) + + # TODO Keep an eye on the zlib repository for an update to disable testing. Don't forget to update CMakePresets + FetchContent_Declare( + zlib + URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip + URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1 + ) + + # Disable warning about no project version. + set(CMAKE_POLICY_DEFAULT_CMP0048 NEW) + # Disable warning about the minimum version of cmake used for bcrypt being deprecated in the future + set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) + + FetchContent_MakeAvailable(zlib) + + set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR}) + set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}") + add_library(ZLIB::ZLIB ALIAS zlib) +else () + message( + FATAL_ERROR + "This platform does not have a way to use zlib.\nCreate an issue on GitHub with your build system so it can be configured." + ) +endif () + +target_link_libraries(dCommon ZLIB::ZLIB) diff --git a/dCommon/ZCompression.cpp b/dCommon/ZCompression.cpp index 70f23500..d5d4c126 100644 --- a/dCommon/ZCompression.cpp +++ b/dCommon/ZCompression.cpp @@ -1,7 +1,5 @@ #include "ZCompression.h" -#ifndef _WIN32 - #include namespace ZCompression { @@ -27,7 +25,6 @@ namespace ZCompression { } deflateEnd(&zInfo); // zlib function return(nRet); - } int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr) { @@ -48,26 +45,6 @@ namespace ZCompression { } inflateEnd(&zInfo); // zlib function return(nRet); - - /* - z_stream zInfo = { 0 }; - zInfo.total_in = zInfo.avail_in = nLenSrc; - zInfo.total_out = zInfo.avail_out = nLenDst; - zInfo.next_in = const_cast(abSrc); - zInfo.next_out = const_cast(abDst); - - int nRet = -1; - nErr = inflateInit(&zInfo); // zlib function - if (nErr == Z_OK) { - nErr = inflate(&zInfo, Z_FINISH); // zlib function - if (nErr == Z_STREAM_END) { - nRet = zInfo.total_out; - } - } - inflateEnd(&zInfo); // zlib function - return(nRet); // -1 or len of output - */ } } -#endif diff --git a/dCommon/ZCompression.h b/dCommon/ZCompression.h index 7b987cfa..22a5ff86 100644 --- a/dCommon/ZCompression.h +++ b/dCommon/ZCompression.h @@ -2,10 +2,6 @@ #include -#include "dPlatforms.h" - -#ifndef DARKFLAME_PLATFORM_WIN32 - namespace ZCompression { int32_t GetMaxCompressedLength(int32_t nLenSrc); @@ -14,4 +10,3 @@ namespace ZCompression { int32_t Decompress(const uint8_t* abSrc, int32_t nLenSrc, uint8_t* abDst, int32_t nLenDst, int32_t& nErr); } -#endif diff --git a/dNet/WorldPackets.cpp b/dNet/WorldPackets.cpp index 23d2c010..f6a8f558 100644 --- a/dNet/WorldPackets.cpp +++ b/dNet/WorldPackets.cpp @@ -164,27 +164,35 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, Entity* ent delete name; delete reputation; -#ifdef _WIN32 - bitStream.Write(data.GetNumberOfBytesUsed() + 1); - bitStream.Write(0); - bitStream.Write((char*)data.GetData(), data.GetNumberOfBytesUsed()); -#else //Compress the data before sending: - const int reservedSize = 5 * 1024 * 1024; - uint8_t compressedData[reservedSize]; + const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed()); + uint8_t* compressedData = new uint8_t[reservedSize]; + + // TODO There should be better handling here for not enough memory... + if (!compressedData) return; + size_t size = ZCompression::Compress(data.GetData(), data.GetNumberOfBytesUsed(), compressedData, reservedSize); + assert(size <= reservedSize); + bitStream.Write(size + 9); //size of data + header bytes (8) bitStream.Write(1); //compressed boolean, true bitStream.Write(data.GetNumberOfBytesUsed()); bitStream.Write(size); + /** + * In practice, this warning serves no purpose for us. We allocate the max memory needed on the heap + * and then compress the data. In the off chance that the compression actually increases the size, + * an assertion is done to prevent bad data from being saved or sent. + */ +#pragma warning(disable:6385) // C6385 Reading invalid data from 'compressedData'. for (size_t i = 0; i < size; i++) bitStream.Write(compressedData[i]); -#endif +#pragma warning(default:6385) - PacketUtils::SavePacket("chardata.bin", (const char*)bitStream.GetData(), static_cast(bitStream.GetNumberOfBytesUsed())); + // PacketUtils::SavePacket("chardata.bin", (const char*)bitStream.GetData(), static_cast(bitStream.GetNumberOfBytesUsed())); SEND_PACKET; + delete[] compressedData; Game::logger->Log("WorldPackets", "Sent CreateCharacter for ID: %llu", entity->GetObjectID()); }