Merge pull request #2781 from janisozaur/zlib

Use zlib for muliplayer game transfer
This commit is contained in:
Ted John 2016-01-20 23:58:37 +00:00
commit ed1ba15163
9 changed files with 136 additions and 30 deletions

View File

@ -46,12 +46,13 @@ endif (DISABLE_NETWORK)
option(STATIC "Create a static build.")
# Not required yet
PKG_CHECK_MODULES(PNG libpng>=1.6)
if (NOT PNG_FOUND)
PKG_CHECK_MODULES(PNG REQUIRED libpng16)
endif (NOT PNG_FOUND)
PKG_CHECK_MODULES(ZLIB REQUIRED zlib)
# Handle creating the rct2 text and data files on OS X and Linux
# See details in src/openrct2.c:openrct2_setup_rct2_segment for how the values
# were derived.
@ -143,9 +144,9 @@ else (STATIC)
endif (STATIC)
if (STATIC)
SET(PNGLIBS ${PNG_STATIC_LIBRARIES})
SET(REQUIREDLIBS ${PNG_STATIC_LIBRARIES} ${ZLIB_STATIC_LIBRARIES})
else (STATIC)
SET(PNGLIBS ${PNG_LIBRARIES})
SET(REQUIREDLIBS ${PNG_LIBRARIES} ${ZLIB_LIBRARIES})
endif (STATIC)
if (NOT DISABLE_HTTP_TWITCH)
@ -163,24 +164,16 @@ if (NOT DISABLE_HTTP_TWITCH)
endif (STATIC)
endif (NOT DISABLE_HTTP_TWITCH)
# speex v1.1.15 is supplied in our zipped library, but distributions provide
# updated version, with required functions extracted out to libspeexdsp.
# This largely takes care of the problem
if (WIN32)
include_directories("lib/libspeex/")
file(GLOB_RECURSE SPEEX_SOURCES "lib/libspeex/*.c")
else (WIN32)
PKG_CHECK_MODULES(SPEEX REQUIRED speexdsp)
endif (WIN32)
PKG_CHECK_MODULES(SPEEX REQUIRED speexdsp)
if (UNIX)
# Include libdl for dlopen
set(DLLIB dl)
endif (UNIX)
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${LIBCURL_INCLUDE_DIRS} ${JANSSON_INCLUDE_DIRS} ${SPEEX_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${LIBCURL_INCLUDE_DIRS} ${JANSSON_INCLUDE_DIRS} ${SPEEX_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS})
LINK_DIRECTORIES(${SDL2_LIBRARY_DIRS} ${JANSSON_LIBRARY_DIRS} ${LIBCURL_LIBRARY_DIRS} ${PNG_LIBRARY_DIRS})
LINK_DIRECTORIES(${SDL2_LIBRARY_DIRS} ${JANSSON_LIBRARY_DIRS} ${LIBCURL_LIBRARY_DIRS} ${PNG_LIBRARY_DIRS} ${ZLIB_LIBRARY_DIRS})
if (WIN32)
# build as library for now, replace with add_executable
@ -213,7 +206,7 @@ endif (UNIX AND NOT APPLE)
# libopenrct2.dll -> openrct2.dll
set_target_properties(${PROJECT} PROPERTIES PREFIX "")
TARGET_LINK_LIBRARIES(${PROJECT} ${SDL2LIBS} ${HTTPLIBS} ${NETWORKLIBS} ${SPEEX_LIBRARIES} ${DLLIB} ${PNGLIBS})
TARGET_LINK_LIBRARIES(${PROJECT} ${SDL2LIBS} ${HTTPLIBS} ${NETWORKLIBS} ${SPEEX_LIBRARIES} ${DLLIB} ${REQUIREDLIBS})
if (APPLE OR STATIC)
FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c)

View File

@ -14,6 +14,7 @@
D435325F1C3472E500BA219B /* libpng.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D435325E1C3472E500BA219B /* libpng.dylib */; };
D43532601C34730200BA219B /* libpng.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D435325E1C3472E500BA219B /* libpng.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
D46105CE1C38828D00DB1EE3 /* scenario_sources.c in Sources */ = {isa = PBXBuildFile; fileRef = D46105CD1C38828D00DB1EE3 /* scenario_sources.c */; };
D47304D51C4FF8250015C0EA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D47304D41C4FF8250015C0EA /* libz.tbd */; };
D4ABAB061C2F812B0080CAD9 /* news_options.c in Sources */ = {isa = PBXBuildFile; fileRef = D4ABAB051C2F812B0080CAD9 /* news_options.c */; };
D4B63B8F1C43025600367A37 /* CommandLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B8A1C43025600367A37 /* CommandLine.cpp */; };
D4B63B901C43025600367A37 /* RootCommands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B8C1C43025600367A37 /* RootCommands.cpp */; };
@ -224,6 +225,7 @@
D41B74721C2125E50080A7B9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = distribution/osx/Assets.xcassets; sourceTree = SOURCE_ROOT; };
D435325E1C3472E500BA219B /* libpng.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libpng.dylib; sourceTree = "<group>"; };
D46105CD1C38828D00DB1EE3 /* scenario_sources.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scenario_sources.c; path = src/scenario_sources.c; sourceTree = "<group>"; };
D47304D41C4FF8250015C0EA /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
D4895D321C23EFDD000CD788 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = distribution/osx/Info.plist; sourceTree = SOURCE_ROOT; };
D497D0781C20FD52002BF46A /* OpenRCT2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenRCT2.app; sourceTree = BUILT_PRODUCTS_DIR; };
D4ABAB051C2F812B0080CAD9 /* news_options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = news_options.c; sourceTree = "<group>"; };
@ -567,6 +569,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D47304D51C4FF8250015C0EA /* libz.tbd in Frameworks */,
D41B73EF1C2101890080A7B9 /* libcurl.tbd in Frameworks */,
D41B741D1C210A7A0080A7B9 /* libiconv.tbd in Frameworks */,
D435325F1C3472E500BA219B /* libpng.dylib in Frameworks */,
@ -1135,6 +1138,7 @@
D41B73EE1C2101890080A7B9 /* libcurl.tbd */,
D41B741C1C210A7A0080A7B9 /* libiconv.tbd */,
D41B73F01C21018C0080A7B9 /* libssl.tbd */,
D47304D41C4FF8250015C0EA /* libz.tbd */,
);
name = system;
sourceTree = "<group>";

View File

@ -320,14 +320,14 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(SolutionDir)lib\include;$(SolutionDir)lib\include\libspeex;$(SolutionDir)lib\include\sdl;$(SolutionDir)lib\include\jansson;$(SolutionDir)lib\include\sdl_ttf;$(SolutionDir)lib\include\libpng;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)lib\include;$(SolutionDir)lib\include\libspeex;$(SolutionDir)lib\include\sdl;$(SolutionDir)lib\include\jansson;$(SolutionDir)lib\include\sdl_ttf;$(SolutionDir)lib\include\libpng;$(SolutionDir)lib\include\zlib;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)lib;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)bin\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>
<LinkIncremental />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(SolutionDir)lib\include;$(SolutionDir)lib\include\libspeex;$(SolutionDir)lib\include\sdl;$(SolutionDir)lib\include\jansson;$(SolutionDir)lib\include\sdl_ttf;$(SolutionDir)lib\include\libpng;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)lib\include;$(SolutionDir)lib\include\libspeex;$(SolutionDir)lib\include\sdl;$(SolutionDir)lib\include\jansson;$(SolutionDir)lib\include\sdl_ttf;$(SolutionDir)lib\include\libpng;$(SolutionDir)lib\include\zlib;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)lib;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)bin\</OutDir>
<IntDir>$(SolutionDir)obj\$(ProjectName)\$(Configuration)\</IntDir>

View File

@ -19,7 +19,7 @@ if [[ $TARGET != "linux" && $TARGET != "docker32" && $SYSTEM != "Darwin" ]]; the
# keep in sync with version in Xcode project
sha256sum=6562ce9e1f37f125e3345bfd8b961777800436bf607b30dc7c964e0e6991ad2c
else
sha256sum=31c5e19d9f794bd5f0e75f20c2b4c3c4664d736b0a4d50c8cde14a9a9007b62d
sha256sum=f124c954bbd0b58c93e5fba46902806bd3637d3a1c5fb8e4b67441052f182df2
fi
libVFile="./libversion"
libdir="./lib"

View File

@ -114,11 +114,6 @@ function install_pkg_config {
cat /usr/local/bin/i686-w64-mingw32-pkg-config
}
function install_local_libs {
mkdir -p lib
cp -rf $cachedir/orctlibs/local/* ./lib/.
}
function os_x_install_mingw_32 {
local mingw_name="mingw-w32-bin_i686-darwin"
local mingw_tar="${mingw_name}_20130531.tar.bz2"
@ -198,7 +193,6 @@ if [[ $TARGET == "windows" || $(uname -s) == "Darwin" ]]; then
calculate_sha256 "$cachedir/orctlibs.zip" > "$libVFile"
echo "Downloaded library with sha256sum: $(cat "$libVFile")"
# Local libs are required for all targets
install_local_libs
# $TARGET == "windows" || $(uname -s) == "Darwin"
fi

View File

@ -988,21 +988,34 @@ void Network::Server_Send_MAP(NetworkConnection* connection)
{
int buffersize = 0x600000;
std::vector<uint8> buffer(buffersize);
bool RLEState = gUseRLE;
gUseRLE = false;
SDL_RWops* rw = SDL_RWFromMem(&buffer[0], buffersize);
scenario_save_network(rw);
gUseRLE = RLEState;
int size = (int)SDL_RWtell(rw);
int chunksize = 1000;
for (int i = 0; i < size; i += chunksize) {
int datasize = (std::min)(chunksize, size - i);
size_t chunksize = 1000;
size_t out_size;
unsigned char *compressed = util_zlib_deflate(&buffer[0], size, &out_size);
unsigned char *header = (unsigned char *)strdup("open2_sv6_zlib");
size_t header_len = strlen((char *)header) + 1; // account for null terminator
header = (unsigned char *)realloc(header, header_len + out_size);
memcpy(&header[header_len], compressed, out_size);
out_size += header_len;
free(compressed);
log_verbose("Sending map of size %u bytes, compressed to %u bytes", size, out_size);
for (int i = 0; i < out_size; i += chunksize) {
int datasize = (std::min)(chunksize, out_size - i);
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_MAP << (uint32)size << (uint32)i;
packet->Write(&buffer[i], datasize);
*packet << (uint32)NETWORK_COMMAND_MAP << (uint32)out_size << (uint32)i;
packet->Write(&header[i], datasize);
if (connection) {
connection->QueuePacket(std::move(packet));
} else {
SendPacketToClients(*packet);
}
}
free(header);
SDL_RWclose(rw);
}
@ -1349,8 +1362,26 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac
memcpy(&chunk_buffer[offset], (void*)packet.Read(chunksize), chunksize);
if (offset + chunksize == size) {
window_network_status_close();
bool has_to_free = false;
unsigned char *data = &chunk_buffer[0];
size_t data_size = size;
// zlib-compressed
if (strcmp("open2_sv6_zlib", (char *)&chunk_buffer[0]) == 0)
{
log_warning("Received zlib-compressed sv6 map");
has_to_free = true;
size_t header_len = strlen("open2_sv6_zlib") + 1;
data = util_zlib_inflate(&chunk_buffer[header_len], size - header_len, &data_size);
if (data == NULL)
{
log_warning("Failed to decompress data sent from server.");
return 0;
}
} else {
log_warning("Assuming received map is in plain sv6 format");
}
SDL_RWops* rw = SDL_RWFromMem(&chunk_buffer[0], size);
SDL_RWops* rw = SDL_RWFromMem(data, data_size);
if (game_load_network(rw)) {
game_load_init();
game_command_queue.clear();
@ -1360,6 +1391,10 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac
_desynchronised = false;
}
SDL_RWclose(rw);
if (has_to_free)
{
free(data);
}
}
}
return 1;

View File

@ -22,6 +22,7 @@
#include "../platform/platform.h"
#include "sawyercoding.h"
#include "../scenario.h"
#include "util.h"
static size_t decode_chunk_rle(const uint8* src_buffer, uint8* dst_buffer, size_t length);
static size_t decode_chunk_repeat(uint8 *buffer, size_t length);
@ -138,6 +139,11 @@ size_t sawyercoding_read_chunk(SDL_RWops* rw, uint8 *buffer)
size_t sawyercoding_write_chunk_buffer(uint8 *dst_file, uint8* buffer, sawyercoding_chunk_header chunkHeader){
uint8 *encode_buffer, *encode_buffer2;
if (gUseRLE == false) {
if (chunkHeader.encoding == CHUNK_ENCODING_RLE || chunkHeader.encoding == CHUNK_ENCODING_RLECOMPRESSED) {
chunkHeader.encoding = CHUNK_ENCODING_NONE;
}
}
switch (chunkHeader.encoding){
case CHUNK_ENCODING_NONE:
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));

View File

@ -21,6 +21,9 @@
#include "util.h"
#include <SDL.h>
#include "../platform/platform.h"
#include "zlib.h"
bool gUseRLE = true;
int squaredmetres_to_squaredfeet(int squaredMetres)
{
@ -313,3 +316,69 @@ uint32 util_rand() {
srand3 = srand3 ^ (srand3 >> 19) ^ temp ^ (temp >> 8);
return srand3;
}
#define CHUNK 128*1024
#define MAX_ZLIB_REALLOC 4*1024*1024
/**
* @brief Inflates zlib-compressed data
* @param data Data to be decompressed
* @param data_in_size Size of data to be decompressed
* @param data_out_size Pointer to a variable where output size will be written. If not 0, it will be used to set initial output buffer size.
* @return Returns a pointer to memory holding decompressed data or NULL on failure.
* @note It is caller's responsibility to free() the returned pointer once done with it.
*/
unsigned char *util_zlib_inflate(unsigned char *data, size_t data_in_size, size_t *data_out_size)
{
int ret = Z_OK;
uLongf out_size = *data_out_size;
if (out_size == 0)
{
// Try to guesstimate the size needed for output data by applying the
// same ratio it would take to compress data_in_size.
out_size = data_in_size * data_in_size / compressBound(data_in_size);
out_size = min(MAX_ZLIB_REALLOC, out_size);
}
size_t buffer_size = out_size;
unsigned char *buffer = malloc(buffer_size);
do {
if (ret == Z_BUF_ERROR)
{
buffer_size *= 2;
out_size = buffer_size;
buffer = realloc(buffer, buffer_size);
}
ret = uncompress(buffer, &out_size, data, data_in_size);
} while (ret != Z_OK);
buffer = realloc(buffer, out_size);
*data_out_size = out_size;
return buffer;
}
/**
* @brief Deflates input using zlib
* @param data Data to be compressed
* @param data_in_size Size of data to be compressed
* @param data_out_size Pointer to a variable where output size will be written
* @return Returns a pointer to memory holding compressed data or NULL on failure.
* @note It is caller's responsibility to free() the returned pointer once done with it.
*/
unsigned char *util_zlib_deflate(unsigned char *data, size_t data_in_size, size_t *data_out_size)
{
int ret = Z_OK;
uLongf out_size = *data_out_size;
size_t buffer_size = compressBound(data_in_size);
unsigned char *buffer = malloc(buffer_size);
do {
if (ret == Z_BUF_ERROR)
{
buffer_size *= 2;
out_size = buffer_size;
buffer = realloc(buffer, buffer_size);
}
ret = compress(buffer, &out_size, data, data_in_size);
} while (ret != Z_OK);
*data_out_size = out_size;
buffer = realloc(buffer, *data_out_size);
return buffer;
}

View File

@ -23,6 +23,8 @@
#include "../common.h"
extern bool gUseRLE;
int squaredmetres_to_squaredfeet(int squaredMetres);
int metres_to_feet(int metres);
int mph_to_kmph(int mph);
@ -52,4 +54,7 @@ bool str_is_null_or_empty(const char *str);
void util_srand(int source);
uint32 util_rand();
unsigned char *util_zlib_deflate(unsigned char *data, size_t data_in_size, size_t *data_out_size);
unsigned char *util_zlib_inflate(unsigned char *data, size_t data_in_size, size_t *data_out_size);
#endif