Merge pull request #951 from worktycho/chunksparsing/structs
Chunksparsing with segments
This commit is contained in:
commit
0b758946ac
1
.gitignore
vendored
1
.gitignore
vendored
@ -48,6 +48,7 @@ world_nether
|
|||||||
CMakeFiles/
|
CMakeFiles/
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
|
CTestTestfile.cmake
|
||||||
Makefile
|
Makefile
|
||||||
|
|
||||||
*.a
|
*.a
|
||||||
|
14
.travis.yml
14
.travis.yml
@ -2,8 +2,15 @@ language: cpp
|
|||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- if [ "$TRAVIS_MCSERVER_BUILD_TYPE" == "COVERAGE" ]; then sudo pip install cpp_coveralls; fi
|
||||||
|
|
||||||
# Build MCServer
|
# Build MCServer
|
||||||
script: cmake . -DBUILD_TOOLS=1 -DSELF_TEST=1 && make -j 2 && cd MCServer/ && (echo stop | $MCSERVER_PATH)
|
script: ./CIbuild.sh
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- ./uploadCoverage.sh
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE MCSERVER_PATH=./MCServer
|
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE MCSERVER_PATH=./MCServer
|
||||||
@ -11,6 +18,11 @@ env:
|
|||||||
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer
|
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer
|
||||||
- TRAVIS_MCSERVER_BUILD_TYPE=DEBUG TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer_debug
|
- TRAVIS_MCSERVER_BUILD_TYPE=DEBUG TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer_debug
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- compiler: gcc
|
||||||
|
env: TRAVIS_MCSERVER_BUILD_TYPE=COVERAGE MCSERVER_PATH=./MCServer
|
||||||
|
|
||||||
# Notification Settings
|
# Notification Settings
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email:
|
||||||
|
11
CIbuild.sh
Executable file
11
CIbuild.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cmake . -DBUILD_TOOLS=1 -DSELF_TEST=1;
|
||||||
|
make -j 2;
|
||||||
|
make -j 2 test;
|
||||||
|
cd MCServer/;
|
||||||
|
if [ "$TRAVIS_MCSERVER_BUILD_TYPE" != "COVERAGE" ]
|
||||||
|
then echo stop | $MCSERVER_PATH;
|
||||||
|
fi
|
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required (VERSION 2.6)
|
cmake_minimum_required (VERSION 2.8.2)
|
||||||
|
|
||||||
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
|
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
|
||||||
enable_language(CXX C)
|
enable_language(CXX C)
|
||||||
@ -14,6 +14,10 @@ if(DEFINED ENV{TRAVIS_MCSERVER_FORCE32})
|
|||||||
set(FORCE32 $ENV{TRAVIS_MCSERVER_FORCE32})
|
set(FORCE32 $ENV{TRAVIS_MCSERVER_FORCE32})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED ENV{TRAVIS_BUILD_WITH_COVERAGE})
|
||||||
|
set(BUILD_WITH_COVERAGE $ENV{TRAVIS_BUILD_WITH_COVERAGE})
|
||||||
|
endif()
|
||||||
|
|
||||||
# This has to be done before any flags have been set up.
|
# This has to be done before any flags have been set up.
|
||||||
if(${BUILD_TOOLS})
|
if(${BUILD_TOOLS})
|
||||||
add_subdirectory(Tools/MCADefrag/)
|
add_subdirectory(Tools/MCADefrag/)
|
||||||
@ -69,3 +73,8 @@ set_exe_flags()
|
|||||||
|
|
||||||
add_subdirectory (src)
|
add_subdirectory (src)
|
||||||
|
|
||||||
|
if(${SELF_TEST})
|
||||||
|
enable_testing()
|
||||||
|
add_subdirectory (tests)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
@ -1,32 +1,41 @@
|
|||||||
macro (add_flags_lnk FLAGS)
|
macro (add_flags_lnk FLAGS)
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_COVERAGE} ${FLAGS}")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
|
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}")
|
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_COVERAGE} ${FLAGS}")
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}")
|
||||||
|
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||||
|
set(CMAKE_MODULE_LINKER_FLAGS_COVERAGE "${CMAKE_MODULE_LINKER_FLAGS_COVERAGE} ${FLAGS}")
|
||||||
|
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(add_flags_cxx FLAGS)
|
macro(add_flags_cxx FLAGS)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
|
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} ${FLAGS}")
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
|
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE} ${FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
|
||||||
macro(set_flags)
|
macro(set_flags)
|
||||||
# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
|
# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/cmake-coverage/")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
include(CodeCoverage)
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -D_DEBUG")
|
||||||
|
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE} -D_DEBUG")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
@ -42,9 +51,10 @@ macro(set_flags)
|
|||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
#on os x clang adds pthread for us but we need to add it for gcc
|
#on os x clang adds pthread for us but we need to add it for gcc
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++11")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
||||||
add_flags_cxx("-stdlib=libc++")
|
add_flags_cxx("-stdlib=libc++")
|
||||||
add_flags_lnk("-stdlib=libc++")
|
add_flags_lnk("-stdlib=libc++")
|
||||||
else()
|
else()
|
||||||
@ -57,6 +67,7 @@ macro(set_flags)
|
|||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
|
||||||
|
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++11")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -97,10 +108,12 @@ macro(set_lib_flags)
|
|||||||
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||||
string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||||
else()
|
else()
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w")
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
|
||||||
|
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -w")
|
||||||
|
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE} -w")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# On Unix we use two dynamic loading libraries dl and ltdl.
|
# On Unix we use two dynamic loading libraries dl and ltdl.
|
||||||
@ -128,7 +141,7 @@ macro(enable_profile)
|
|||||||
|
|
||||||
# Declare the profiling configurations:
|
# Declare the profiling configurations:
|
||||||
SET(CMAKE_CXX_FLAGS_DEBUGPROFILE
|
SET(CMAKE_CXX_FLAGS_DEBUGPROFILE
|
||||||
"${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}"
|
"${CMAKE_CXX_FLAGS_DEBUG} ${CXX_PROFILING}"
|
||||||
CACHE STRING "Flags used by the C++ compiler during profile builds."
|
CACHE STRING "Flags used by the C++ compiler during profile builds."
|
||||||
FORCE )
|
FORCE )
|
||||||
SET(CMAKE_C_FLAGS_DEBUGPROFILE
|
SET(CMAKE_C_FLAGS_DEBUGPROFILE
|
||||||
@ -171,7 +184,11 @@ macro(enable_profile)
|
|||||||
CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
|
CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
|
||||||
CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE )
|
CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE )
|
||||||
# The configuration types need to be set after their respective c/cxx/linker flags and before the project directive
|
# The configuration types need to be set after their respective c/cxx/linker flags and before the project directive
|
||||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
|
if(MSVC)
|
||||||
|
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
|
||||||
|
else()
|
||||||
|
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile;Coverage" CACHE STRING "" FORCE)
|
||||||
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(set_exe_flags)
|
macro(set_exe_flags)
|
||||||
@ -180,10 +197,12 @@ macro(set_exe_flags)
|
|||||||
# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
|
# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
|
||||||
# the important warnings are turned on using #pragma in Globals.h
|
# the important warnings are turned on using #pragma in Globals.h
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||||
string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
|
string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
|
||||||
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||||
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||||
|
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE}")
|
||||||
|
string(REPLACE "-w" "" CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE}")
|
||||||
add_flags_cxx("-Wall -Wextra -Wno-unused-parameter -Wno-error=switch")
|
add_flags_cxx("-Wall -Wextra -Wno-unused-parameter -Wno-error=switch")
|
||||||
|
|
||||||
# we support non-IEEE 754 fpus so can make no guarentees about error
|
# we support non-IEEE 754 fpus so can make no guarentees about error
|
||||||
|
160
lib/cmake-coverage/CodeCoverage.cmake
Normal file
160
lib/cmake-coverage/CodeCoverage.cmake
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#
|
||||||
|
# 2012-01-31, Lars Bilke
|
||||||
|
# - Enable Code Coverage
|
||||||
|
#
|
||||||
|
# 2013-09-17, Joakim Söderberg
|
||||||
|
# - Added support for Clang.
|
||||||
|
# - Some additional usage instructions.
|
||||||
|
#
|
||||||
|
# USAGE:
|
||||||
|
# 1. Copy this file into your cmake modules path.
|
||||||
|
#
|
||||||
|
# 2. Add the following line to your CMakeLists.txt:
|
||||||
|
# INCLUDE(CodeCoverage)
|
||||||
|
#
|
||||||
|
# 3. Set compiler flags to turn off optimization and enable coverage:
|
||||||
|
# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||||
|
# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||||
|
#
|
||||||
|
# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
|
||||||
|
# which runs your test executable and produces a lcov code coverage report:
|
||||||
|
# Example:
|
||||||
|
# SETUP_TARGET_FOR_COVERAGE(
|
||||||
|
# my_coverage_target # Name for custom target.
|
||||||
|
# test_driver # Name of the test driver executable that runs the tests.
|
||||||
|
# # NOTE! This should always have a ZERO as exit code
|
||||||
|
# # otherwise the coverage generation will not complete.
|
||||||
|
# coverage # Name of output directory.
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# 4. Build a Debug build:
|
||||||
|
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||||
|
# make
|
||||||
|
# make my_coverage_target
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
# Check prereqs
|
||||||
|
FIND_PROGRAM( GCOV_PATH gcov )
|
||||||
|
FIND_PROGRAM( LCOV_PATH lcov )
|
||||||
|
FIND_PROGRAM( GENHTML_PATH genhtml )
|
||||||
|
FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
|
||||||
|
|
||||||
|
IF(NOT GCOV_PATH)
|
||||||
|
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
|
||||||
|
ENDIF() # NOT GCOV_PATH
|
||||||
|
|
||||||
|
IF(NOT CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
# Clang version 3.0.0 and greater now supports gcov as well.
|
||||||
|
MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.")
|
||||||
|
|
||||||
|
IF(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX
|
||||||
|
|
||||||
|
SET(CMAKE_CXX_FLAGS_COVERAGE
|
||||||
|
"-g -O0 --coverage -fprofile-arcs -ftest-coverage"
|
||||||
|
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
SET(CMAKE_C_FLAGS_COVERAGE
|
||||||
|
"-g -O0 --coverage -fprofile-arcs -ftest-coverage"
|
||||||
|
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||||
|
""
|
||||||
|
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||||
|
""
|
||||||
|
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
MARK_AS_ADVANCED(
|
||||||
|
CMAKE_CXX_FLAGS_COVERAGE
|
||||||
|
CMAKE_C_FLAGS_COVERAGE
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||||
|
|
||||||
|
IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage"))
|
||||||
|
MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" )
|
||||||
|
ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
|
||||||
|
|
||||||
|
|
||||||
|
# Param _targetname The name of new the custom make target
|
||||||
|
# Param _testrunner The name of the target which runs the tests.
|
||||||
|
# MUST return ZERO always, even on errors.
|
||||||
|
# If not, no coverage report will be created!
|
||||||
|
# Param _outputname lcov output is generated as _outputname.info
|
||||||
|
# HTML report is generated in _outputname/index.html
|
||||||
|
# Optional fourth parameter is passed as arguments to _testrunner
|
||||||
|
# Pass them in list form, e.g.: "-j;2" for -j 2
|
||||||
|
FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname)
|
||||||
|
|
||||||
|
IF(NOT LCOV_PATH)
|
||||||
|
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
|
||||||
|
ENDIF() # NOT LCOV_PATH
|
||||||
|
|
||||||
|
IF(NOT GENHTML_PATH)
|
||||||
|
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
|
||||||
|
ENDIF() # NOT GENHTML_PATH
|
||||||
|
|
||||||
|
# Setup target
|
||||||
|
ADD_CUSTOM_TARGET(${_targetname}
|
||||||
|
|
||||||
|
# Cleanup lcov
|
||||||
|
${LCOV_PATH} --directory . --zerocounters
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
COMMAND ${_testrunner} ${ARGV3}
|
||||||
|
|
||||||
|
# Capturing lcov counters and generating report
|
||||||
|
COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info
|
||||||
|
COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'tests/*' '/usr/*' --output-file ${_outputname}.info.cleaned
|
||||||
|
COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned
|
||||||
|
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show info where to find the report
|
||||||
|
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."
|
||||||
|
)
|
||||||
|
|
||||||
|
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE
|
||||||
|
|
||||||
|
# Param _targetname The name of new the custom make target
|
||||||
|
# Param _testrunner The name of the target which runs the tests
|
||||||
|
# Param _outputname cobertura output is generated as _outputname.xml
|
||||||
|
# Optional fourth parameter is passed as arguments to _testrunner
|
||||||
|
# Pass them in list form, e.g.: "-j;2" for -j 2
|
||||||
|
FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname)
|
||||||
|
|
||||||
|
IF(NOT PYTHON_EXECUTABLE)
|
||||||
|
MESSAGE(FATAL_ERROR "Python not found! Aborting...")
|
||||||
|
ENDIF() # NOT PYTHON_EXECUTABLE
|
||||||
|
|
||||||
|
IF(NOT GCOVR_PATH)
|
||||||
|
MESSAGE(FATAL_ERROR "gcovr not found! Aborting...")
|
||||||
|
ENDIF() # NOT GCOVR_PATH
|
||||||
|
|
||||||
|
ADD_CUSTOM_TARGET(${_targetname}
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
${_testrunner} ${ARGV3}
|
||||||
|
|
||||||
|
# Running gcovr
|
||||||
|
COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show info where to find the report
|
||||||
|
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT "Cobertura code coverage report saved in ${_outputname}.xml."
|
||||||
|
)
|
||||||
|
|
||||||
|
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
|
23
lib/cmake-coverage/LICENSE
Normal file
23
lib/cmake-coverage/LICENSE
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
@ -1,5 +1,11 @@
|
|||||||
|
|
||||||
if(NOT TARGET polarssl)
|
if(NOT TARGET polarssl)
|
||||||
message("including polarssl")
|
message("including polarssl")
|
||||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl EXCLUDE_FROM_ALL )
|
if (SELF_TEST)
|
||||||
|
set(ENABLE_TESTING OFF CACHE BOOL "Disable tests")
|
||||||
|
set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable programs")
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl)
|
||||||
|
else()
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "StringUtils.h"
|
||||||
|
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "OSSupport/GZipFile.h"
|
#include "OSSupport/GZipFile.h"
|
||||||
#include "Blocks/BlockHandler.h"
|
#include "Blocks/BlockHandler.h"
|
||||||
#include "Cuboid.h"
|
#include "Cuboid.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1835,116 +1835,88 @@ bool cBlockArea::cChunkReader::Coords(int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockArea::cChunkReader::BlockTypes(const BLOCKTYPE * a_BlockTypes)
|
void cBlockArea::cChunkReader::ChunkData(const cChunkData & a_BlockBuffer)
|
||||||
{
|
{
|
||||||
if (m_Area.m_BlockTypes == NULL)
|
|
||||||
{
|
{
|
||||||
// Don't want BlockTypes
|
if (m_Area.m_BlockTypes != NULL)
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SizeY = m_Area.m_Size.y;
|
|
||||||
int MinY = m_Origin.y;
|
|
||||||
|
|
||||||
// SizeX, SizeZ are the dmensions of the block data to copy from the current chunk (size of the geometric union)
|
|
||||||
// OffX, OffZ are the offsets of the current chunk data from the area origin
|
|
||||||
// BaseX, BaseZ are the offsets of the area data within the current chunk from the chunk borders
|
|
||||||
int SizeX = cChunkDef::Width;
|
|
||||||
int SizeZ = cChunkDef::Width;
|
|
||||||
int OffX, OffZ;
|
|
||||||
int BaseX, BaseZ;
|
|
||||||
OffX = m_CurrentChunkX * cChunkDef::Width - m_Origin.x;
|
|
||||||
if (OffX < 0)
|
|
||||||
{
|
|
||||||
BaseX = -OffX;
|
|
||||||
SizeX += OffX; // SizeX is decreased, OffX is negative
|
|
||||||
OffX = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BaseX = 0;
|
|
||||||
}
|
|
||||||
OffZ = m_CurrentChunkZ * cChunkDef::Width - m_Origin.z;
|
|
||||||
if (OffZ < 0)
|
|
||||||
{
|
|
||||||
BaseZ = -OffZ;
|
|
||||||
SizeZ += OffZ; // SizeZ is decreased, OffZ is negative
|
|
||||||
OffZ = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BaseZ = 0;
|
|
||||||
}
|
|
||||||
// If the chunk extends beyond the area in the X or Z axis, cut off the Size:
|
|
||||||
if ((m_CurrentChunkX + 1) * cChunkDef::Width > m_Origin.x + m_Area.m_Size.x)
|
|
||||||
{
|
|
||||||
SizeX -= (m_CurrentChunkX + 1) * cChunkDef::Width - (m_Origin.x + m_Area.m_Size.x);
|
|
||||||
}
|
|
||||||
if ((m_CurrentChunkZ + 1) * cChunkDef::Width > m_Origin.z + m_Area.m_Size.z)
|
|
||||||
{
|
|
||||||
SizeZ -= (m_CurrentChunkZ + 1) * cChunkDef::Width - (m_Origin.z + m_Area.m_Size.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int y = 0; y < SizeY; y++)
|
|
||||||
{
|
|
||||||
int ChunkY = MinY + y;
|
|
||||||
int AreaY = y;
|
|
||||||
for (int z = 0; z < SizeZ; z++)
|
|
||||||
{
|
{
|
||||||
int ChunkZ = BaseZ + z;
|
int SizeY = m_Area.m_Size.y;
|
||||||
int AreaZ = OffZ + z;
|
int MinY = m_Origin.y;
|
||||||
for (int x = 0; x < SizeX; x++)
|
|
||||||
|
// SizeX, SizeZ are the dimensions of the block data to copy from the current chunk (size of the geometric union)
|
||||||
|
// OffX, OffZ are the offsets of the current chunk data from the area origin
|
||||||
|
// BaseX, BaseZ are the offsets of the area data within the current chunk from the chunk borders
|
||||||
|
int SizeX = cChunkDef::Width;
|
||||||
|
int SizeZ = cChunkDef::Width;
|
||||||
|
int OffX, OffZ;
|
||||||
|
int BaseX, BaseZ;
|
||||||
|
OffX = m_CurrentChunkX * cChunkDef::Width - m_Origin.x;
|
||||||
|
if (OffX < 0)
|
||||||
{
|
{
|
||||||
int ChunkX = BaseX + x;
|
BaseX = -OffX;
|
||||||
int AreaX = OffX + x;
|
SizeX += OffX; // SizeX is decreased, OffX is negative
|
||||||
m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = cChunkDef::GetBlock(a_BlockTypes, ChunkX, ChunkY, ChunkZ);
|
OffX = 0;
|
||||||
} // for x
|
}
|
||||||
} // for z
|
else
|
||||||
} // for y
|
{
|
||||||
}
|
BaseX = 0;
|
||||||
|
}
|
||||||
|
OffZ = m_CurrentChunkZ * cChunkDef::Width - m_Origin.z;
|
||||||
|
if (OffZ < 0)
|
||||||
|
{
|
||||||
|
BaseZ = -OffZ;
|
||||||
|
SizeZ += OffZ; // SizeZ is decreased, OffZ is negative
|
||||||
|
OffZ = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BaseZ = 0;
|
||||||
|
}
|
||||||
|
// If the chunk extends beyond the area in the X or Z axis, cut off the Size:
|
||||||
|
if ((m_CurrentChunkX + 1) * cChunkDef::Width > m_Origin.x + m_Area.m_Size.x)
|
||||||
|
{
|
||||||
|
SizeX -= (m_CurrentChunkX + 1) * cChunkDef::Width - (m_Origin.x + m_Area.m_Size.x);
|
||||||
|
}
|
||||||
|
if ((m_CurrentChunkZ + 1) * cChunkDef::Width > m_Origin.z + m_Area.m_Size.z)
|
||||||
|
{
|
||||||
|
SizeZ -= (m_CurrentChunkZ + 1) * cChunkDef::Width - (m_Origin.z + m_Area.m_Size.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < SizeY; y++)
|
||||||
|
{
|
||||||
|
int ChunkY = MinY + y;
|
||||||
|
int AreaY = y;
|
||||||
void cBlockArea::cChunkReader::BlockMeta(const NIBBLETYPE * a_BlockMetas)
|
for (int z = 0; z < SizeZ; z++)
|
||||||
{
|
{
|
||||||
if (m_Area.m_BlockMetas == NULL)
|
int ChunkZ = BaseZ + z;
|
||||||
{
|
int AreaZ = OffZ + z;
|
||||||
// Don't want metas
|
for (int x = 0; x < SizeX; x++)
|
||||||
return;
|
{
|
||||||
|
int ChunkX = BaseX + x;
|
||||||
|
int AreaX = OffX + x;
|
||||||
|
m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockBuffer.GetBlock(ChunkX, ChunkY, ChunkZ);
|
||||||
|
} // for x
|
||||||
|
} // for z
|
||||||
|
} // for y
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CopyNibbles(m_Area.m_BlockMetas, a_BlockMetas);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (m_Area.m_BlockMetas != NULL)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockArea::cChunkReader::BlockLight(const NIBBLETYPE * a_BlockLight)
|
|
||||||
{
|
|
||||||
if (m_Area.m_BlockLight == NULL)
|
|
||||||
{
|
{
|
||||||
// Don't want light
|
a_BlockBuffer.CopyMetas(m_Area.m_BlockMetas);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
CopyNibbles(m_Area.m_BlockLight, a_BlockLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (m_Area.m_BlockLight != NULL)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockArea::cChunkReader::BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight)
|
|
||||||
{
|
|
||||||
if (m_Area.m_BlockSkyLight == NULL)
|
|
||||||
{
|
{
|
||||||
// Don't want skylight
|
a_BlockBuffer.CopyBlockLight(m_Area.m_BlockLight);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
CopyNibbles(m_Area.m_BlockSkyLight, a_BlockSkyLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (m_Area.m_BlockSkyLight != NULL)
|
||||||
|
{
|
||||||
|
a_BlockBuffer.CopySkyLight(m_Area.m_BlockSkyLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "ForEachChunkProvider.h"
|
#include "ForEachChunkProvider.h"
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
#include "ChunkDataCallback.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -316,11 +317,8 @@ protected:
|
|||||||
void CopyNibbles(NIBBLETYPE * a_AreaDst, const NIBBLETYPE * a_ChunkSrc);
|
void CopyNibbles(NIBBLETYPE * a_AreaDst, const NIBBLETYPE * a_ChunkSrc);
|
||||||
|
|
||||||
// cChunkDataCallback overrides:
|
// cChunkDataCallback overrides:
|
||||||
virtual bool Coords (int a_ChunkX, int a_ChunkZ) override;
|
virtual bool Coords(int a_ChunkX, int a_ChunkZ) override;
|
||||||
virtual void BlockTypes (const BLOCKTYPE * a_BlockTypes) override;
|
virtual void ChunkData(const cChunkData & a_BlockTypes) override;
|
||||||
virtual void BlockMeta (const NIBBLETYPE * a_BlockMetas) override;
|
|
||||||
virtual void BlockLight (const NIBBLETYPE * a_BlockLight) override;
|
|
||||||
virtual void BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) override;
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
typedef NIBBLETYPE * NIBBLEARRAY;
|
typedef NIBBLETYPE * NIBBLEARRAY;
|
||||||
|
185
src/Chunk.cpp
185
src/Chunk.cpp
@ -238,26 +238,12 @@ void cChunk::MarkLoadFailed(void)
|
|||||||
|
|
||||||
void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
||||||
{
|
{
|
||||||
a_Callback.HeightMap (&m_HeightMap);
|
a_Callback.HeightMap(&m_HeightMap);
|
||||||
a_Callback.BiomeData (&m_BiomeMap);
|
a_Callback.BiomeData(&m_BiomeMap);
|
||||||
|
|
||||||
COMPRESSED_BLOCKTYPE Blocks = m_BlockTypes;
|
a_Callback.LightIsValid(m_IsLightValid);
|
||||||
Blocks.resize(NumBlocks);
|
|
||||||
a_Callback.BlockTypes (&Blocks[0]);
|
|
||||||
|
|
||||||
COMPRESSED_NIBBLETYPE Metas = m_BlockMeta;
|
a_Callback.ChunkData(m_ChunkData);
|
||||||
Metas.resize(NumBlocks / 2);
|
|
||||||
a_Callback.BlockMeta (&Metas[0]);
|
|
||||||
|
|
||||||
a_Callback.LightIsValid (m_IsLightValid);
|
|
||||||
|
|
||||||
COMPRESSED_NIBBLETYPE BlockLights = m_BlockLight;
|
|
||||||
BlockLights.resize(NumBlocks / 2);
|
|
||||||
a_Callback.BlockLight (&BlockLights[0]);
|
|
||||||
|
|
||||||
COMPRESSED_NIBBLETYPE BlockSkyLights = m_BlockSkyLight;
|
|
||||||
BlockSkyLights.resize(NumBlocks / 2, 0xff);
|
|
||||||
a_Callback.BlockSkyLight(&BlockSkyLights[0]);
|
|
||||||
|
|
||||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
||||||
{
|
{
|
||||||
@ -296,48 +282,10 @@ void cChunk::SetAllData(
|
|||||||
CalculateHeightmap(a_BlockTypes);
|
CalculateHeightmap(a_BlockTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
int IdxWhereNonEmptyStarts = 0;
|
m_ChunkData.SetBlockTypes(a_BlockTypes);
|
||||||
{ // Blocktype compression
|
m_ChunkData.SetMetas(a_BlockMeta);
|
||||||
unsigned char Highest = 0;
|
m_ChunkData.SetBlockLight(a_BlockLight);
|
||||||
int X = 0, Z = 0;
|
m_ChunkData.SetSkyLight(a_BlockSkyLight);
|
||||||
m_BlockTypes.clear();
|
|
||||||
|
|
||||||
for (int x = 0; x < Width; x++)
|
|
||||||
{
|
|
||||||
for (int z = 0; z < Width; z++)
|
|
||||||
{
|
|
||||||
unsigned char Height = m_HeightMap[x + z * Width];
|
|
||||||
if (Height > Highest)
|
|
||||||
{
|
|
||||||
Highest = Height;
|
|
||||||
X = x; Z = z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IdxWhereNonEmptyStarts = MakeIndexNoCheck(X, Highest + 1, Z);
|
|
||||||
|
|
||||||
m_BlockTypes.insert(m_BlockTypes.end(), &a_BlockTypes[0], &a_BlockTypes[IdxWhereNonEmptyStarts]);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ // Blockmeta compression
|
|
||||||
m_BlockMeta.clear();
|
|
||||||
m_BlockMeta.insert(m_BlockMeta.end(), &a_BlockMeta[0], &a_BlockMeta[IdxWhereNonEmptyStarts / 2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a_BlockLight != NULL)
|
|
||||||
{
|
|
||||||
// Compress blocklight
|
|
||||||
m_BlockLight.clear();
|
|
||||||
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[IdxWhereNonEmptyStarts / 2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a_BlockSkyLight != NULL)
|
|
||||||
{
|
|
||||||
// Compress skylight
|
|
||||||
m_BlockSkyLight.clear();
|
|
||||||
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_BlockSkyLight[0], &a_BlockSkyLight[IdxWhereNonEmptyStarts / 2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL);
|
m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL);
|
||||||
|
|
||||||
@ -378,15 +326,9 @@ void cChunk::SetLight(
|
|||||||
// TODO: We might get cases of wrong lighting when a chunk changes in the middle of a lighting calculation.
|
// TODO: We might get cases of wrong lighting when a chunk changes in the middle of a lighting calculation.
|
||||||
// Postponing until we see how bad it is :)
|
// Postponing until we see how bad it is :)
|
||||||
|
|
||||||
{ // Compress blocklight
|
m_ChunkData.SetBlockLight(a_BlockLight);
|
||||||
m_BlockLight.clear();
|
|
||||||
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[m_BlockTypes.size() / 2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ // Compress skylight
|
m_ChunkData.SetSkyLight(a_SkyLight);
|
||||||
m_BlockSkyLight.clear();
|
|
||||||
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_SkyLight[0], &a_SkyLight[m_BlockTypes.size() / 2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_IsLightValid = true;
|
m_IsLightValid = true;
|
||||||
}
|
}
|
||||||
@ -397,8 +339,7 @@ void cChunk::SetLight(
|
|||||||
|
|
||||||
void cChunk::GetBlockTypes(BLOCKTYPE * a_BlockTypes)
|
void cChunk::GetBlockTypes(BLOCKTYPE * a_BlockTypes)
|
||||||
{
|
{
|
||||||
std::copy(m_BlockTypes.begin(), m_BlockTypes.end(), a_BlockTypes);
|
m_ChunkData.CopyBlockTypes(a_BlockTypes);
|
||||||
std::fill_n(&a_BlockTypes[m_BlockTypes.size()], NumBlocks - m_BlockTypes.size(), E_BLOCK_AIR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -684,8 +625,7 @@ void cChunk::Tick(float a_Dt)
|
|||||||
|
|
||||||
void cChunk::TickBlock(int a_RelX, int a_RelY, int a_RelZ)
|
void cChunk::TickBlock(int a_RelX, int a_RelY, int a_RelZ)
|
||||||
{
|
{
|
||||||
unsigned Index = MakeIndex(a_RelX, a_RelY, a_RelZ);
|
cBlockHandler * Handler = BlockHandler(GetBlock(a_RelX, a_RelY, a_RelZ));
|
||||||
cBlockHandler * Handler = BlockHandler(GetBlock(Index));
|
|
||||||
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
||||||
cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap());
|
cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap());
|
||||||
cBlockInServerPluginInterface PluginInterface(*this->GetWorld());
|
cBlockInServerPluginInterface PluginInterface(*this->GetWorld());
|
||||||
@ -810,19 +750,18 @@ void cChunk::CheckBlocks()
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<unsigned int> ToTickBlocks;
|
std::vector<Vector3i> ToTickBlocks;
|
||||||
std::swap(m_ToTickBlocks, ToTickBlocks);
|
std::swap(m_ToTickBlocks, ToTickBlocks);
|
||||||
|
|
||||||
cChunkInterface ChunkInterface(m_World->GetChunkMap());
|
cChunkInterface ChunkInterface(m_World->GetChunkMap());
|
||||||
cBlockInServerPluginInterface PluginInterface(*m_World);
|
cBlockInServerPluginInterface PluginInterface(*m_World);
|
||||||
|
|
||||||
for (std::vector<unsigned int>::const_iterator itr = ToTickBlocks.begin(), end = ToTickBlocks.end(); itr != end; ++itr)
|
for (std::vector<Vector3i>::const_iterator itr = ToTickBlocks.begin(), end = ToTickBlocks.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
unsigned int index = (*itr);
|
Vector3i Pos = (*itr);
|
||||||
Vector3i BlockPos = IndexToCoordinate(index);
|
|
||||||
|
|
||||||
cBlockHandler * Handler = BlockHandler(GetBlock(index));
|
cBlockHandler * Handler = BlockHandler(GetBlock(Pos));
|
||||||
Handler->Check(ChunkInterface, PluginInterface, BlockPos.x, BlockPos.y, BlockPos.z, *this);
|
Handler->Check(ChunkInterface, PluginInterface, Pos.x, Pos.y, Pos.z, *this);
|
||||||
} // for itr - ToTickBlocks[]
|
} // for itr - ToTickBlocks[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,8 +804,7 @@ void cChunk::TickBlocks(void)
|
|||||||
continue; // It's all air up here
|
continue; // It's all air up here
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Index = MakeIndexNoCheck(m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
cBlockHandler * Handler = BlockHandler(GetBlock(m_BlockTickX, m_BlockTickY, m_BlockTickZ));
|
||||||
cBlockHandler * Handler = BlockHandler(GetBlock(Index));
|
|
||||||
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
||||||
Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface, *this, m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface, *this, m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
||||||
} // for i - tickblocks
|
} // for i - tickblocks
|
||||||
@ -1258,9 +1196,8 @@ bool cChunk::UnboundedRelGetBlockLights(int a_RelX, int a_RelY, int a_RelZ, NIBB
|
|||||||
// The chunk is not available, bail out
|
// The chunk is not available, bail out
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int idx = Chunk->MakeIndex(a_RelX, a_RelY, a_RelZ);
|
a_BlockLight = Chunk->GetBlockLight(a_RelX, a_RelY, a_RelZ);
|
||||||
a_BlockLight = Chunk->GetBlockLight(idx);
|
a_SkyLight = Chunk->GetSkyLight(a_RelX, a_RelY, a_RelZ);
|
||||||
a_SkyLight = Chunk->GetSkyLight(idx);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1466,10 +1403,8 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
|
|||||||
{
|
{
|
||||||
FastSetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
|
FastSetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
|
||||||
|
|
||||||
const int index = MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
|
||||||
|
|
||||||
// Tick this block and its neighbors:
|
// Tick this block and its neighbors:
|
||||||
m_ToTickBlocks.push_back(index);
|
m_ToTickBlocks.push_back(Vector3i(a_RelX, a_RelY, a_RelZ));
|
||||||
QueueTickBlockNeighbors(a_RelX, a_RelY, a_RelZ);
|
QueueTickBlockNeighbors(a_RelX, a_RelY, a_RelZ);
|
||||||
|
|
||||||
// If there was a block entity, remove it:
|
// If there was a block entity, remove it:
|
||||||
@ -1533,7 +1468,7 @@ void cChunk::QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ));
|
m_ToTickBlocks.push_back(Vector3i(a_RelX, a_RelY, a_RelZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1571,9 +1506,8 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
|||||||
|
|
||||||
ASSERT(IsValid());
|
ASSERT(IsValid());
|
||||||
|
|
||||||
const int index = MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
const BLOCKTYPE OldBlockType = GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||||
const BLOCKTYPE OldBlockType = GetBlock(index);
|
const BLOCKTYPE OldBlockMeta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||||
const BLOCKTYPE OldBlockMeta = GetNibble(m_BlockMeta, index);
|
|
||||||
if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta))
|
if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -1581,11 +1515,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
|||||||
|
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
|
|
||||||
if ((size_t)index >= m_BlockTypes.size())
|
m_ChunkData.SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType);
|
||||||
{
|
|
||||||
m_BlockTypes.resize(index + 1);
|
|
||||||
}
|
|
||||||
m_BlockTypes[index] = a_BlockType;
|
|
||||||
|
|
||||||
// The client doesn't need to distinguish between stationary and nonstationary fluids:
|
// The client doesn't need to distinguish between stationary and nonstationary fluids:
|
||||||
if (
|
if (
|
||||||
@ -1601,7 +1531,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
|||||||
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta));
|
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta));
|
||||||
}
|
}
|
||||||
|
|
||||||
SetNibble(m_BlockMeta, index, a_BlockMeta);
|
m_ChunkData.SetMeta(a_RelX, a_RelY, a_RelZ, a_BlockMeta);
|
||||||
|
|
||||||
// ONLY recalculate lighting if it's necessary!
|
// ONLY recalculate lighting if it's necessary!
|
||||||
if (
|
if (
|
||||||
@ -1624,7 +1554,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
|||||||
{
|
{
|
||||||
for (int y = a_RelY - 1; y > 0; --y)
|
for (int y = a_RelY - 1; y > 0; --y)
|
||||||
{
|
{
|
||||||
if (GetBlock(MakeIndexNoCheck(a_RelX, y, a_RelZ)) != E_BLOCK_AIR)
|
if (GetBlock(a_RelX, y, a_RelZ) != E_BLOCK_AIR)
|
||||||
{
|
{
|
||||||
m_HeightMap[a_RelX + a_RelZ * Width] = (unsigned char)y;
|
m_HeightMap[a_RelX + a_RelZ * Width] = (unsigned char)y;
|
||||||
break;
|
break;
|
||||||
@ -1638,39 +1568,18 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta)
|
|
||||||
{
|
|
||||||
if (GetNibble(m_BlockMeta, a_BlockIdx) == a_Meta)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MarkDirty();
|
|
||||||
SetNibble(m_BlockMeta, a_BlockIdx, a_Meta);
|
|
||||||
Vector3i Coords(IndexToCoordinate(a_BlockIdx));
|
|
||||||
|
|
||||||
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, Coords.x, Coords.y, Coords.z, GetBlock(a_BlockIdx), a_Meta));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client)
|
void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client)
|
||||||
{
|
{
|
||||||
// The coords must be valid, because the upper level already does chunk lookup. No need to check them again.
|
|
||||||
// There's an debug-time assert in MakeIndexNoCheck anyway
|
|
||||||
unsigned int index = MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
|
||||||
|
|
||||||
if (a_Client == NULL)
|
if (a_Client == NULL)
|
||||||
{
|
{
|
||||||
// Queue the block for all clients in the chunk (will be sent in Tick())
|
// Queue the block for all clients in the chunk (will be sent in Tick())
|
||||||
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, GetBlock(index), GetMeta(index)));
|
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3i wp = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ);
|
Vector3i wp = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ);
|
||||||
a_Client->SendBlockChange(wp.x, wp.y, wp.z, GetBlock(index), GetMeta(index));
|
a_Client->SendBlockChange(wp.x, wp.y, wp.z, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ));
|
||||||
|
|
||||||
// FS #268 - if a BlockEntity digging is cancelled by a plugin, the entire block entity must be re-sent to the client:
|
// FS #268 - if a BlockEntity digging is cancelled by a plugin, the entire block entity must be re-sent to the client:
|
||||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), end = m_BlockEntities.end(); itr != end; ++itr)
|
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), end = m_BlockEntities.end(); itr != end; ++itr)
|
||||||
@ -2529,27 +2438,7 @@ BLOCKTYPE cChunk::GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
|
|||||||
return 0; // Clip
|
return 0; // Clip
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetBlock(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ));
|
return m_ChunkData.GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BLOCKTYPE cChunk::GetBlock(int a_BlockIdx) const
|
|
||||||
{
|
|
||||||
if ((a_BlockIdx < 0) || (a_BlockIdx >= NumBlocks))
|
|
||||||
{
|
|
||||||
ASSERT(!"GetBlock(idx) out of bounds!");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((size_t)a_BlockIdx >= m_BlockTypes.size())
|
|
||||||
{
|
|
||||||
return E_BLOCK_AIR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_BlockTypes[a_BlockIdx];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2558,9 +2447,8 @@ BLOCKTYPE cChunk::GetBlock(int a_BlockIdx) const
|
|||||||
|
|
||||||
void cChunk::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
|
void cChunk::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
|
||||||
{
|
{
|
||||||
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
a_BlockType = GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||||
a_BlockType = GetBlock(Idx);
|
a_BlockMeta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||||
a_BlockMeta = cChunkDef::GetNibble(m_BlockMeta, Idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2569,11 +2457,10 @@ void cChunk::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_
|
|||||||
|
|
||||||
void cChunk::GetBlockInfo(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight)
|
void cChunk::GetBlockInfo(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight)
|
||||||
{
|
{
|
||||||
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
a_BlockType = GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||||
a_BlockType = GetBlock(Idx);
|
a_Meta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||||
a_Meta = cChunkDef::GetNibble(m_BlockMeta, Idx);
|
a_SkyLight = m_ChunkData.GetSkyLight(a_RelX, a_RelY, a_RelZ);
|
||||||
a_SkyLight = cChunkDef::GetNibble(m_BlockSkyLight, Idx);
|
a_BlockLight = m_ChunkData.GetBlockLight(a_RelX, a_RelY, a_RelZ);
|
||||||
a_BlockLight = cChunkDef::GetNibble(m_BlockLight, Idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
37
src/Chunk.h
37
src/Chunk.h
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "Entities/Entity.h"
|
#include "Entities/Entity.h"
|
||||||
#include "ChunkDef.h"
|
#include "ChunkDef.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
#include "Simulator/FireSimulator.h"
|
#include "Simulator/FireSimulator.h"
|
||||||
#include "Simulator/SandSimulator.h"
|
#include "Simulator/SandSimulator.h"
|
||||||
@ -66,6 +67,7 @@ public:
|
|||||||
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
|
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
|
||||||
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP // Neighbor chunks
|
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP // Neighbor chunks
|
||||||
);
|
);
|
||||||
|
cChunk(cChunk & other);
|
||||||
~cChunk();
|
~cChunk();
|
||||||
|
|
||||||
bool IsValid(void) const {return m_IsValid; } // Returns true if the chunk block data is valid (loaded / generated)
|
bool IsValid(void) const {return m_IsValid; } // Returns true if the chunk block data is valid (loaded / generated)
|
||||||
@ -154,7 +156,7 @@ public:
|
|||||||
|
|
||||||
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta ); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
|
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta ); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
|
||||||
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const;
|
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const;
|
||||||
BLOCKTYPE GetBlock(int a_BlockIdx) const;
|
BLOCKTYPE GetBlock(Vector3i a_cords) const { return GetBlock(a_cords.x, a_cords.y, a_cords.z);}
|
||||||
void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
|
void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
|
||||||
void GetBlockInfo (int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
|
void GetBlockInfo (int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
|
||||||
|
|
||||||
@ -320,15 +322,23 @@ public:
|
|||||||
m_BlockTickZ = a_RelZ;
|
m_BlockTickZ = a_RelZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const { return cChunkDef::GetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ); }
|
inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
|
||||||
inline NIBBLETYPE GetMeta(int a_BlockIdx) const { return cChunkDef::GetNibble(m_BlockMeta, a_BlockIdx); }
|
{
|
||||||
inline void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { SetMeta(MakeIndex(a_RelX, a_RelY, a_RelZ), a_Meta); }
|
return m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||||
void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta);
|
}
|
||||||
|
inline void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
|
||||||
|
{
|
||||||
|
bool hasChanged = m_ChunkData.SetMeta(a_RelX, a_RelY, a_RelZ, a_Meta);
|
||||||
|
if (hasChanged)
|
||||||
|
{
|
||||||
|
MarkDirty();
|
||||||
|
|
||||||
inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockLight, a_RelX, a_RelY, a_RelZ); }
|
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, GetBlock(a_RelX, a_RelY, a_RelZ), a_Meta));
|
||||||
inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_RelX, a_RelY, a_RelZ, true); }
|
}
|
||||||
inline NIBBLETYPE GetBlockLight(int a_Idx) const {return cChunkDef::GetNibble(m_BlockLight, a_Idx); }
|
}
|
||||||
inline NIBBLETYPE GetSkyLight (int a_Idx) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_Idx, true); }
|
|
||||||
|
inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return m_ChunkData.GetBlockLight(a_RelX, a_RelY, a_RelZ); }
|
||||||
|
inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return m_ChunkData.GetSkyLight(a_RelX, a_RelY, a_RelZ); }
|
||||||
|
|
||||||
/** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
/** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
||||||
bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
|
bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
|
||||||
@ -403,8 +413,8 @@ private:
|
|||||||
bool m_IsSaving; // True if the chunk is being saved
|
bool m_IsSaving; // True if the chunk is being saved
|
||||||
bool m_HasLoadFailed; // True if chunk failed to load and hasn't been generated yet since then
|
bool m_HasLoadFailed; // True if chunk failed to load and hasn't been generated yet since then
|
||||||
|
|
||||||
std::vector<unsigned int> m_ToTickBlocks;
|
std::vector<Vector3i> m_ToTickBlocks;
|
||||||
sSetBlockVector m_PendingSendBlocks; ///< Blocks that have changed and need to be sent to all clients
|
sSetBlockVector m_PendingSendBlocks; ///< Blocks that have changed and need to be sent to all clients
|
||||||
|
|
||||||
sSetBlockQueueVector m_SetBlockQueue; ///< Block changes that are queued to a specific tick
|
sSetBlockQueueVector m_SetBlockQueue; ///< Block changes that are queued to a specific tick
|
||||||
|
|
||||||
@ -420,10 +430,7 @@ private:
|
|||||||
cWorld * m_World;
|
cWorld * m_World;
|
||||||
cChunkMap * m_ChunkMap;
|
cChunkMap * m_ChunkMap;
|
||||||
|
|
||||||
COMPRESSED_BLOCKTYPE m_BlockTypes;
|
cChunkData m_ChunkData;
|
||||||
COMPRESSED_NIBBLETYPE m_BlockMeta;
|
|
||||||
COMPRESSED_NIBBLETYPE m_BlockLight;
|
|
||||||
COMPRESSED_NIBBLETYPE m_BlockSkyLight;
|
|
||||||
|
|
||||||
cChunkDef::HeightMap m_HeightMap;
|
cChunkDef::HeightMap m_HeightMap;
|
||||||
cChunkDef::BiomeMap m_BiomeMap;
|
cChunkDef::BiomeMap m_BiomeMap;
|
||||||
|
592
src/ChunkData.cpp
Normal file
592
src/ChunkData.cpp
Normal file
@ -0,0 +1,592 @@
|
|||||||
|
|
||||||
|
// ChunkData.cpp
|
||||||
|
|
||||||
|
// Implements the cChunkData class that represents the block's type, meta, blocklight and skylight storage for a chunk
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns true if all a_Array's elements between [0] and [a_NumElements - 1] are equal to a_Value. */
|
||||||
|
template <typename T> inline bool IsAllValue(const T * a_Array, size_t a_NumElements, T a_Value)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < a_NumElements; i++)
|
||||||
|
{
|
||||||
|
if (a_Array[i] != a_Value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cChunkData::cChunkData(void)
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
// auto_ptr style interface for memory management
|
||||||
|
: m_IsOwner(true)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
m_Sections[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cChunkData::~cChunkData()
|
||||||
|
{
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
// auto_ptr style interface for memory management
|
||||||
|
if (!m_IsOwner)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
Free(m_Sections[i]);
|
||||||
|
m_Sections[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
// auto_ptr style interface for memory management
|
||||||
|
cChunkData::cChunkData(const cChunkData & a_Other) :
|
||||||
|
m_IsOwner(true)
|
||||||
|
{
|
||||||
|
// Move contents and ownership from a_Other to this, pointer-wise:
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
m_Sections[i] = a_Other.m_Sections[i];
|
||||||
|
}
|
||||||
|
a_Other.m_IsOwner = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cChunkData & cChunkData::operator =(const cChunkData & a_Other)
|
||||||
|
{
|
||||||
|
// If assigning to self, no-op
|
||||||
|
if (&a_Other == this)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free any currently held contents:
|
||||||
|
if (m_IsOwner)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
Free(m_Sections[i]);
|
||||||
|
m_Sections[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move contents and ownership from a_Other to this, pointer-wise:
|
||||||
|
m_IsOwner = true;
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
m_Sections[i] = a_Other.m_Sections[i];
|
||||||
|
}
|
||||||
|
a_Other.m_IsOwner = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// unique_ptr style interface for memory management
|
||||||
|
cChunkData::cChunkData(cChunkData && other)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
m_Sections[i] = other.m_Sections[i];
|
||||||
|
other.m_Sections[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cChunkData & cChunkData::operator =(cChunkData && other)
|
||||||
|
{
|
||||||
|
if (&other != this)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
Free(m_Sections[i]);
|
||||||
|
m_Sections[i] = other.m_Sections[i];
|
||||||
|
other.m_Sections[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BLOCKTYPE cChunkData::GetBlock(int a_X, int a_Y, int a_Z) const
|
||||||
|
{
|
||||||
|
ASSERT((a_X >= 0) && (a_X < cChunkDef::Width));
|
||||||
|
ASSERT((a_Y >= 0) && (a_Y < cChunkDef::Height));
|
||||||
|
ASSERT((a_Z >= 0) && (a_Z < cChunkDef::Width));
|
||||||
|
int Section = a_Y / SectionHeight;
|
||||||
|
if (m_Sections[Section] != NULL)
|
||||||
|
{
|
||||||
|
int Index = cChunkDef::MakeIndexNoCheck(a_X, a_Y - (Section * SectionHeight), a_Z);
|
||||||
|
return m_Sections[Section]->m_BlockTypes[Index];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(a_RelX >= cChunkDef::Width) || (a_RelX < 0) ||
|
||||||
|
(a_RelY >= cChunkDef::Height) || (a_RelY < 0) ||
|
||||||
|
(a_RelZ >= cChunkDef::Width) || (a_RelZ < 0)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT(!"cChunkData::SetMeta(): index out of range!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Section = a_RelY / SectionHeight;
|
||||||
|
if (m_Sections[Section] == NULL)
|
||||||
|
{
|
||||||
|
if (a_Block == 0x00)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_Sections[Section] = Allocate();
|
||||||
|
if (m_Sections[Section] == NULL)
|
||||||
|
{
|
||||||
|
ASSERT(!"Failed to allocate a new section in Chunkbuffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ZeroSection(m_Sections[Section]);
|
||||||
|
}
|
||||||
|
int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ);
|
||||||
|
m_Sections[Section]->m_BlockTypes[Index] = a_Block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NIBBLETYPE cChunkData::GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(a_RelX < cChunkDef::Width) && (a_RelX > -1) &&
|
||||||
|
(a_RelY < cChunkDef::Height) && (a_RelY > -1) &&
|
||||||
|
(a_RelZ < cChunkDef::Width) && (a_RelZ > -1))
|
||||||
|
{
|
||||||
|
int Section = a_RelY / SectionHeight;
|
||||||
|
if (m_Sections[Section] != NULL)
|
||||||
|
{
|
||||||
|
int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ);
|
||||||
|
return (m_Sections[Section]->m_BlockMetas[Index / 2] >> ((Index & 1) * 4)) & 0x0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(!"cChunkData::GetMeta(): coords out of chunk range!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunkData::SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(a_RelX >= cChunkDef::Width) || (a_RelX < 0) ||
|
||||||
|
(a_RelY >= cChunkDef::Height) || (a_RelY < 0) ||
|
||||||
|
(a_RelZ >= cChunkDef::Width) || (a_RelZ < 0)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT(!"cChunkData::SetMeta(): index out of range!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Section = a_RelY / SectionHeight;
|
||||||
|
if (m_Sections[Section] == NULL)
|
||||||
|
{
|
||||||
|
if ((a_Nibble & 0xf) == 0x00)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_Sections[Section] = Allocate();
|
||||||
|
if (m_Sections[Section] == NULL)
|
||||||
|
{
|
||||||
|
ASSERT(!"Failed to allocate a new section in Chunkbuffer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ZeroSection(m_Sections[Section]);
|
||||||
|
}
|
||||||
|
int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ);
|
||||||
|
NIBBLETYPE oldval = m_Sections[Section]->m_BlockMetas[Index / 2] >> ((Index & 1) * 4) & 0xf;
|
||||||
|
m_Sections[Section]->m_BlockMetas[Index / 2] = static_cast<NIBBLETYPE>(
|
||||||
|
(m_Sections[Section]->m_BlockMetas[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble
|
||||||
|
((a_Nibble & 0x0f) << ((Index & 1) * 4)) // The nibble being set
|
||||||
|
);
|
||||||
|
return oldval == a_Nibble;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NIBBLETYPE cChunkData::GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(a_RelX < cChunkDef::Width) && (a_RelX > -1) &&
|
||||||
|
(a_RelY < cChunkDef::Height) && (a_RelY > -1) &&
|
||||||
|
(a_RelZ < cChunkDef::Width) && (a_RelZ > -1)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int Section = a_RelY / SectionHeight;
|
||||||
|
if (m_Sections[Section] != NULL)
|
||||||
|
{
|
||||||
|
int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ);
|
||||||
|
return (m_Sections[Section]->m_BlockLight[Index / 2] >> ((Index & 1) * 4)) & 0x0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(!"cChunkData::GetMeta(): coords out of chunk range!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NIBBLETYPE cChunkData::GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const
|
||||||
|
{
|
||||||
|
if ((a_RelX < cChunkDef::Width) && (a_RelX > -1) && (a_RelY < cChunkDef::Height) && (a_RelY > -1) && (a_RelZ < cChunkDef::Width) && (a_RelZ > -1))
|
||||||
|
{
|
||||||
|
int Section = a_RelY / SectionHeight;
|
||||||
|
if (m_Sections[Section] != NULL)
|
||||||
|
{
|
||||||
|
int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY - (Section * SectionHeight), a_RelZ);
|
||||||
|
return (m_Sections[Section]->m_BlockLight[Index / 2] >> ((Index & 1) * 4)) & 0x0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0xF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(!"cChunkData::GetMeta(): coords out of chunk range!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cChunkData cChunkData::Copy(void) const
|
||||||
|
{
|
||||||
|
cChunkData copy;
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
copy.m_Sections[i] = Allocate();
|
||||||
|
*copy.m_Sections[i] = *m_Sections[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::CopyBlockTypes(BLOCKTYPE * a_Dest, size_t a_Idx, size_t a_Length) const
|
||||||
|
{
|
||||||
|
size_t ToSkip = a_Idx;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
size_t StartPos = 0;
|
||||||
|
if (ToSkip > 0)
|
||||||
|
{
|
||||||
|
StartPos = std::min(ToSkip, +SectionBlockCount);
|
||||||
|
ToSkip -= StartPos;
|
||||||
|
}
|
||||||
|
if (StartPos < SectionBlockCount)
|
||||||
|
{
|
||||||
|
size_t ToCopy = std::min(+SectionBlockCount - StartPos, a_Length);
|
||||||
|
a_Length -= ToCopy;
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
BLOCKTYPE * blockbuffer = m_Sections[i]->m_BlockTypes;
|
||||||
|
memcpy(&a_Dest[(i * SectionBlockCount) + StartPos - a_Idx], blockbuffer + StartPos, sizeof(BLOCKTYPE) * ToCopy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&a_Dest[(i * SectionBlockCount) - a_Idx], 0, sizeof(BLOCKTYPE) * ToCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::CopyMetas(NIBBLETYPE * a_Dest) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
memcpy(&a_Dest[i * SectionBlockCount / 2], &m_Sections[i]->m_BlockMetas, sizeof(m_Sections[i]->m_BlockMetas));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&a_Dest[i * SectionBlockCount / 2], 0, sizeof(m_Sections[i]->m_BlockMetas));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::CopyBlockLight(NIBBLETYPE * a_Dest) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
memcpy(&a_Dest[i * SectionBlockCount / 2], &m_Sections[i]->m_BlockLight, sizeof(m_Sections[i]->m_BlockLight));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&a_Dest[i * SectionBlockCount / 2], 0, sizeof(m_Sections[i]->m_BlockLight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::CopySkyLight(NIBBLETYPE * a_Dest) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
memcpy(&a_Dest[i * SectionBlockCount / 2], &m_Sections[i]->m_BlockSkyLight, sizeof(m_Sections[i]->m_BlockSkyLight));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&a_Dest[i * SectionBlockCount / 2], 0xff, sizeof(m_Sections[i]->m_BlockSkyLight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::SetBlockTypes(const BLOCKTYPE * a_Src)
|
||||||
|
{
|
||||||
|
ASSERT(a_Src != NULL);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
// If the section is already allocated, copy the data into it:
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
memcpy(m_Sections[i]->m_BlockTypes, &a_Src[i * SectionBlockCount], sizeof(m_Sections[i]->m_BlockTypes));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The section doesn't exist, find out if it is needed:
|
||||||
|
if (IsAllValue(a_Src + i * SectionBlockCount, SectionBlockCount, (const BLOCKTYPE)0))
|
||||||
|
{
|
||||||
|
// No need for the section, the data is all-air
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the section and copy the data into it:
|
||||||
|
m_Sections[i] = Allocate();
|
||||||
|
memcpy(m_Sections[i]->m_BlockTypes, &a_Src[i * SectionBlockCount], sizeof(m_Sections[i]->m_BlockTypes));
|
||||||
|
memset(m_Sections[i]->m_BlockMetas, 0x00, sizeof(m_Sections[i]->m_BlockMetas));
|
||||||
|
memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight));
|
||||||
|
memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight));
|
||||||
|
} // for i - m_Sections[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::SetMetas(const NIBBLETYPE * a_Src)
|
||||||
|
{
|
||||||
|
ASSERT(a_Src != NULL);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
// If the section is already allocated, copy the data into it:
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
memcpy(m_Sections[i]->m_BlockMetas, &a_Src[i * SectionBlockCount / 2], sizeof(m_Sections[i]->m_BlockMetas));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The section doesn't exist, find out if it is needed:
|
||||||
|
if (IsAllValue(a_Src + i * SectionBlockCount / 2, SectionBlockCount / 2, (NIBBLETYPE)0))
|
||||||
|
{
|
||||||
|
// No need for the section, the data is all zeroes
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the section and copy the data into it:
|
||||||
|
m_Sections[i] = Allocate();
|
||||||
|
memcpy(m_Sections[i]->m_BlockMetas, &a_Src[i * SectionBlockCount / 2], sizeof(m_Sections[i]->m_BlockMetas));
|
||||||
|
memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes));
|
||||||
|
memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight));
|
||||||
|
memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight));
|
||||||
|
} // for i - m_Sections[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::SetBlockLight(const NIBBLETYPE * a_Src)
|
||||||
|
{
|
||||||
|
if (a_Src == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
// If the section is already allocated, copy the data into it:
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
memcpy(m_Sections[i]->m_BlockLight, &a_Src[i * SectionBlockCount / 2], sizeof(m_Sections[i]->m_BlockLight));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The section doesn't exist, find out if it is needed:
|
||||||
|
if (IsAllValue(a_Src + i * SectionBlockCount / 2, SectionBlockCount / 2, (NIBBLETYPE)0))
|
||||||
|
{
|
||||||
|
// No need for the section, the data is all zeroes
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the section and copy the data into it:
|
||||||
|
m_Sections[i] = Allocate();
|
||||||
|
memcpy(m_Sections[i]->m_BlockLight, &a_Src[i * SectionBlockCount / 2], sizeof(m_Sections[i]->m_BlockLight));
|
||||||
|
memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes));
|
||||||
|
memset(m_Sections[i]->m_BlockMetas, 0x00, sizeof(m_Sections[i]->m_BlockMetas));
|
||||||
|
memset(m_Sections[i]->m_BlockSkyLight, 0xff, sizeof(m_Sections[i]->m_BlockSkyLight));
|
||||||
|
} // for i - m_Sections[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::SetSkyLight(const NIBBLETYPE * a_Src)
|
||||||
|
{
|
||||||
|
if (a_Src == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NumSections; i++)
|
||||||
|
{
|
||||||
|
// If the section is already allocated, copy the data into it:
|
||||||
|
if (m_Sections[i] != NULL)
|
||||||
|
{
|
||||||
|
memcpy(m_Sections[i]->m_BlockSkyLight, &a_Src[i * SectionBlockCount / 2], sizeof(m_Sections[i]->m_BlockSkyLight));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The section doesn't exist, find out if it is needed:
|
||||||
|
if (IsAllValue(a_Src + i * SectionBlockCount / 2, SectionBlockCount / 2, (NIBBLETYPE)0xff))
|
||||||
|
{
|
||||||
|
// No need for the section, the data is all zeroes
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the section and copy the data into it:
|
||||||
|
m_Sections[i] = Allocate();
|
||||||
|
memcpy(m_Sections[i]->m_BlockSkyLight, &a_Src[i * SectionBlockCount / 2], sizeof(m_Sections[i]->m_BlockSkyLight));
|
||||||
|
memset(m_Sections[i]->m_BlockTypes, 0x00, sizeof(m_Sections[i]->m_BlockTypes));
|
||||||
|
memset(m_Sections[i]->m_BlockMetas, 0x00, sizeof(m_Sections[i]->m_BlockMetas));
|
||||||
|
memset(m_Sections[i]->m_BlockLight, 0x00, sizeof(m_Sections[i]->m_BlockLight));
|
||||||
|
} // for i - m_Sections[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cChunkData::sChunkSection * cChunkData::Allocate(void)
|
||||||
|
{
|
||||||
|
// TODO: Use an allocation pool
|
||||||
|
return new cChunkData::sChunkSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::Free(cChunkData::sChunkSection * a_Section)
|
||||||
|
{
|
||||||
|
// TODO: Use an allocation pool
|
||||||
|
delete a_Section;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkData::ZeroSection(cChunkData::sChunkSection * a_Section) const
|
||||||
|
{
|
||||||
|
memset(a_Section->m_BlockTypes, 0x00, sizeof(a_Section->m_BlockTypes));
|
||||||
|
memset(a_Section->m_BlockMetas, 0x00, sizeof(a_Section->m_BlockMetas));
|
||||||
|
memset(a_Section->m_BlockLight, 0x00, sizeof(a_Section->m_BlockLight));
|
||||||
|
memset(a_Section->m_BlockSkyLight, 0xff, sizeof(a_Section->m_BlockSkyLight));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
125
src/ChunkData.h
Normal file
125
src/ChunkData.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
|
||||||
|
// ChunkData.h
|
||||||
|
|
||||||
|
// Declares the cChunkData class that represents the block's type, meta, blocklight and skylight storage for a chunk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
|
#include "ChunkDef.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
// auto_ptr style interface for memory management
|
||||||
|
#else
|
||||||
|
// unique_ptr style interface for memory management
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class cChunkData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
cChunkData(void);
|
||||||
|
~cChunkData();
|
||||||
|
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
// auto_ptr style interface for memory management
|
||||||
|
cChunkData(const cChunkData & a_Other);
|
||||||
|
cChunkData & operator =(const cChunkData & a_Other);
|
||||||
|
#else
|
||||||
|
// unique_ptr style interface for memory management
|
||||||
|
cChunkData(cChunkData && a_Other);
|
||||||
|
cChunkData & operator =(cChunkData && a_ther);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BLOCKTYPE GetBlock(int a_X, int a_Y, int a_Z) const;
|
||||||
|
void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block);
|
||||||
|
|
||||||
|
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const;
|
||||||
|
bool SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble);
|
||||||
|
|
||||||
|
NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const;
|
||||||
|
|
||||||
|
NIBBLETYPE GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const;
|
||||||
|
|
||||||
|
/** Creates a (deep) copy of self. */
|
||||||
|
cChunkData Copy(void) const;
|
||||||
|
|
||||||
|
/** Copies the blocktype data into the specified flat array.
|
||||||
|
Optionally, only a part of the data is copied, as specified by the a_Idx and a_Length parameters. */
|
||||||
|
void CopyBlockTypes(BLOCKTYPE * a_Dest, size_t a_Idx = 0, size_t a_Length = cChunkDef::NumBlocks) const;
|
||||||
|
|
||||||
|
/** Copies the metadata into the specified flat array. */
|
||||||
|
void CopyMetas(NIBBLETYPE * a_Dest) const;
|
||||||
|
|
||||||
|
/** Copies the block light data into the specified flat array. */
|
||||||
|
void CopyBlockLight(NIBBLETYPE * a_Dest) const;
|
||||||
|
|
||||||
|
/** Copies the skylight data into the specified flat array. */
|
||||||
|
void CopySkyLight (NIBBLETYPE * a_Dest) const;
|
||||||
|
|
||||||
|
/** Copies the blocktype data from the specified flat array into the internal representation.
|
||||||
|
Allocates sections that are needed for the operation.
|
||||||
|
Requires that a_Src is a valid pointer. */
|
||||||
|
void SetBlockTypes(const BLOCKTYPE * a_Src);
|
||||||
|
|
||||||
|
/** Copies the metadata from the specified flat array into the internal representation.
|
||||||
|
Allocates sectios that are needed for the operation.
|
||||||
|
Requires that a_Src is a valid pointer. */
|
||||||
|
void SetMetas(const NIBBLETYPE * a_Src);
|
||||||
|
|
||||||
|
/** Copies the blocklight data from the specified flat array into the internal representation.
|
||||||
|
Allocates sectios that are needed for the operation.
|
||||||
|
Allows a_Src to be NULL, in which case it doesn't do anything. */
|
||||||
|
void SetBlockLight(const NIBBLETYPE * a_Src);
|
||||||
|
|
||||||
|
/** Copies the skylight data from the specified flat array into the internal representation.
|
||||||
|
Allocates sectios that are needed for the operation.
|
||||||
|
Allows a_Src to be NULL, in which case it doesn't do anything. */
|
||||||
|
void SetSkyLight(const NIBBLETYPE * a_Src);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static const size_t SectionHeight = 16;
|
||||||
|
static const size_t NumSections = (cChunkDef::Height / SectionHeight);
|
||||||
|
static const size_t SectionBlockCount = SectionHeight * cChunkDef::Width * cChunkDef::Width;
|
||||||
|
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
// auto_ptr style interface for memory management
|
||||||
|
mutable bool m_IsOwner;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sChunkSection {
|
||||||
|
BLOCKTYPE m_BlockTypes [SectionBlockCount];
|
||||||
|
NIBBLETYPE m_BlockMetas [SectionBlockCount / 2];
|
||||||
|
NIBBLETYPE m_BlockLight [SectionBlockCount / 2];
|
||||||
|
NIBBLETYPE m_BlockSkyLight[SectionBlockCount / 2];
|
||||||
|
};
|
||||||
|
|
||||||
|
sChunkSection * m_Sections[NumSections];
|
||||||
|
|
||||||
|
/** Allocates a new section. Entry-point to custom allocators. */
|
||||||
|
static sChunkSection * Allocate(void);
|
||||||
|
|
||||||
|
/** Frees the specified section, previously allocated using Allocate().
|
||||||
|
Note that a_Section may be NULL. */
|
||||||
|
static void Free(sChunkSection * a_Section);
|
||||||
|
|
||||||
|
/** Sets the data in the specified section to their default values. */
|
||||||
|
void ZeroSection(sChunkSection * a_Section) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
127
src/ChunkDataCallback.h
Normal file
127
src/ChunkDataCallback.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
|
||||||
|
// ChunkDataCallback.h
|
||||||
|
|
||||||
|
// Declares the cChunkDataCallback interface and several trivial descendants, for reading chunk data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Interface class used for getting data out of a chunk using the GetAllData() function.
|
||||||
|
Implementation must use the pointers immediately and NOT store any of them for later use
|
||||||
|
The virtual methods are called in the same order as they're declared here.
|
||||||
|
*/
|
||||||
|
class cChunkDataCallback abstract
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~cChunkDataCallback() {}
|
||||||
|
|
||||||
|
/** Called before any other callbacks to inform of the current coords
|
||||||
|
(only in processes where multiple chunks can be processed, such as cWorld::ForEachChunkInRect()).
|
||||||
|
If false is returned, the chunk is skipped.
|
||||||
|
*/
|
||||||
|
virtual bool Coords(int a_ChunkX, int a_ChunkZ) { UNUSED(a_ChunkX); UNUSED(a_ChunkZ); return true; };
|
||||||
|
|
||||||
|
/// Called once to provide heightmap data
|
||||||
|
virtual void HeightMap(const cChunkDef::HeightMap * a_HeightMap) {UNUSED(a_HeightMap); };
|
||||||
|
|
||||||
|
/// Called once to provide biome data
|
||||||
|
virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) {UNUSED(a_BiomeMap); };
|
||||||
|
|
||||||
|
/// Called once to let know if the chunk lighting is valid. Return value is ignored
|
||||||
|
virtual void LightIsValid(bool a_IsLightValid) {UNUSED(a_IsLightValid); };
|
||||||
|
|
||||||
|
/// Called once to export block info
|
||||||
|
virtual void ChunkData(const cChunkData & a_Buffer) {UNUSED(a_Buffer); };
|
||||||
|
|
||||||
|
/// Called for each entity in the chunk
|
||||||
|
virtual void Entity(cEntity * a_Entity) {UNUSED(a_Entity); };
|
||||||
|
|
||||||
|
/// Called for each blockentity in the chunk
|
||||||
|
virtual void BlockEntity(cBlockEntity * a_Entity) {UNUSED(a_Entity); };
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** A simple implementation of the cChunkDataCallback interface that collects all block data into a buffer
|
||||||
|
*/
|
||||||
|
class cChunkDataCollector :
|
||||||
|
public cChunkDataCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
cChunkData m_BlockData;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void ChunkData(const cChunkData & a_BlockData) override
|
||||||
|
{
|
||||||
|
m_BlockData = a_BlockData.Copy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** A simple implementation of the cChunkDataCallback interface that collects all block data into a single buffer
|
||||||
|
*/
|
||||||
|
class cChunkDataArrayCollector :
|
||||||
|
public cChunkDataCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Must be unsigned char instead of BLOCKTYPE or NIBBLETYPE, because it houses both.
|
||||||
|
unsigned char m_BlockData[cChunkDef::BlockDataSize];
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void ChunkData(const cChunkData & a_ChunkBuffer) override
|
||||||
|
{
|
||||||
|
a_ChunkBuffer.CopyBlockTypes(m_BlockData);
|
||||||
|
a_ChunkBuffer.CopyMetas(m_BlockData + cChunkDef::NumBlocks);
|
||||||
|
a_ChunkBuffer.CopyBlockLight(m_BlockData + 3 * cChunkDef::NumBlocks / 2);
|
||||||
|
a_ChunkBuffer.CopySkyLight(m_BlockData + 2 * cChunkDef::NumBlocks);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** A simple implementation of the cChunkDataCallback interface that collects all block data into separate buffers */
|
||||||
|
class cChunkDataSeparateCollector :
|
||||||
|
public cChunkDataCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
cChunkDef::BlockTypes m_BlockTypes;
|
||||||
|
cChunkDef::BlockNibbles m_BlockMetas;
|
||||||
|
cChunkDef::BlockNibbles m_BlockLight;
|
||||||
|
cChunkDef::BlockNibbles m_BlockSkyLight;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void ChunkData(const cChunkData & a_ChunkBuffer) override
|
||||||
|
{
|
||||||
|
a_ChunkBuffer.CopyBlockTypes(m_BlockTypes);
|
||||||
|
a_ChunkBuffer.CopyMetas(m_BlockMetas);
|
||||||
|
a_ChunkBuffer.CopyBlockLight(m_BlockLight);
|
||||||
|
a_ChunkBuffer.CopySkyLight(m_BlockSkyLight);
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
130
src/ChunkDef.h
130
src/ChunkDef.h
@ -330,136 +330,6 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Interface class used for getting data out of a chunk using the GetAllData() function.
|
|
||||||
Implementation must use the pointers immediately and NOT store any of them for later use
|
|
||||||
The virtual methods are called in the same order as they're declared here.
|
|
||||||
*/
|
|
||||||
class cChunkDataCallback abstract
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~cChunkDataCallback() {}
|
|
||||||
|
|
||||||
/** Called before any other callbacks to inform of the current coords
|
|
||||||
(only in processes where multiple chunks can be processed, such as cWorld::ForEachChunkInRect()).
|
|
||||||
If false is returned, the chunk is skipped.
|
|
||||||
*/
|
|
||||||
virtual bool Coords(int a_ChunkX, int a_ChunkZ) { UNUSED(a_ChunkX); UNUSED(a_ChunkZ); return true; };
|
|
||||||
|
|
||||||
/// Called once to provide heightmap data
|
|
||||||
virtual void HeightMap(const cChunkDef::HeightMap * a_HeightMap) {UNUSED(a_HeightMap); };
|
|
||||||
|
|
||||||
/// Called once to provide biome data
|
|
||||||
virtual void BiomeData (const cChunkDef::BiomeMap * a_BiomeMap) {UNUSED(a_BiomeMap); };
|
|
||||||
|
|
||||||
/// Called once to export block types
|
|
||||||
virtual void BlockTypes (const BLOCKTYPE * a_Type) {UNUSED(a_Type); };
|
|
||||||
|
|
||||||
/// Called once to export block meta
|
|
||||||
virtual void BlockMeta (const NIBBLETYPE * a_Meta) {UNUSED(a_Meta); };
|
|
||||||
|
|
||||||
/// Called once to let know if the chunk lighting is valid. Return value is used to control if BlockLight() and BlockSkyLight() are called next (if true)
|
|
||||||
virtual bool LightIsValid(bool a_IsLightValid) {UNUSED(a_IsLightValid); return true; };
|
|
||||||
|
|
||||||
/// Called once to export block light
|
|
||||||
virtual void BlockLight (const NIBBLETYPE * a_BlockLight) {UNUSED(a_BlockLight); };
|
|
||||||
|
|
||||||
/// Called once to export sky light
|
|
||||||
virtual void BlockSkyLight(const NIBBLETYPE * a_SkyLight) {UNUSED(a_SkyLight); };
|
|
||||||
|
|
||||||
/// Called for each entity in the chunk
|
|
||||||
virtual void Entity(cEntity * a_Entity) {UNUSED(a_Entity); };
|
|
||||||
|
|
||||||
/// Called for each blockentity in the chunk
|
|
||||||
virtual void BlockEntity(cBlockEntity * a_Entity) {UNUSED(a_Entity); };
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** A simple implementation of the cChunkDataCallback interface that collects all block data into a single buffer
|
|
||||||
*/
|
|
||||||
class cChunkDataCollector :
|
|
||||||
public cChunkDataCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Must be unsigned char instead of BLOCKTYPE or NIBBLETYPE, because it houses both.
|
|
||||||
unsigned char m_BlockData[cChunkDef::BlockDataSize];
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
virtual void BlockTypes(const BLOCKTYPE * a_BlockTypes) override
|
|
||||||
{
|
|
||||||
memcpy(m_BlockData, a_BlockTypes, sizeof(cChunkDef::BlockTypes));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void BlockMeta(const NIBBLETYPE * a_BlockMeta) override
|
|
||||||
{
|
|
||||||
memcpy(m_BlockData + cChunkDef::NumBlocks, a_BlockMeta, cChunkDef::NumBlocks / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void BlockLight(const NIBBLETYPE * a_BlockLight) override
|
|
||||||
{
|
|
||||||
memcpy(m_BlockData + 3 * cChunkDef::NumBlocks / 2, a_BlockLight, cChunkDef::NumBlocks / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) override
|
|
||||||
{
|
|
||||||
memcpy(m_BlockData + 2 * cChunkDef::NumBlocks, a_BlockSkyLight, cChunkDef::NumBlocks / 2);
|
|
||||||
}
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** A simple implementation of the cChunkDataCallback interface that collects all block data into a separate buffers
|
|
||||||
*/
|
|
||||||
class cChunkDataSeparateCollector :
|
|
||||||
public cChunkDataCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
cChunkDef::BlockTypes m_BlockTypes;
|
|
||||||
cChunkDef::BlockNibbles m_BlockMetas;
|
|
||||||
cChunkDef::BlockNibbles m_BlockLight;
|
|
||||||
cChunkDef::BlockNibbles m_BlockSkyLight;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
virtual void BlockTypes(const BLOCKTYPE * a_BlockTypes) override
|
|
||||||
{
|
|
||||||
memcpy(m_BlockTypes, a_BlockTypes, sizeof(m_BlockTypes));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void BlockMeta(const NIBBLETYPE * a_BlockMeta) override
|
|
||||||
{
|
|
||||||
memcpy(m_BlockMetas, a_BlockMeta, sizeof(m_BlockMetas));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void BlockLight(const NIBBLETYPE * a_BlockLight) override
|
|
||||||
{
|
|
||||||
memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight) override
|
|
||||||
{
|
|
||||||
memcpy(m_BlockSkyLight, a_BlockSkyLight, sizeof(m_BlockSkyLight));
|
|
||||||
}
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Interface class used for comparing clients of two chunks.
|
/** Interface class used for comparing clients of two chunks.
|
||||||
Used primarily for entity moving while both chunks are locked.
|
Used primarily for entity moving while both chunks are locked.
|
||||||
*/
|
*/
|
||||||
|
@ -219,9 +219,8 @@ bool cChunkMap::LockedGetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTY
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Index = cChunkDef::MakeIndexNoCheck(a_BlockX, a_BlockY, a_BlockZ);
|
a_BlockType = Chunk->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
a_BlockType = Chunk->GetBlock(Index);
|
a_BlockMeta = Chunk->GetMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
a_BlockMeta = Chunk->GetMeta(Index);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,8 +241,7 @@ bool cChunkMap::LockedGetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ, BLO
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Index = cChunkDef::MakeIndexNoCheck(a_BlockX, a_BlockY, a_BlockZ);
|
a_BlockType = Chunk->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
a_BlockType = Chunk->GetBlock(Index);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,8 +262,7 @@ bool cChunkMap::LockedGetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIB
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Index = cChunkDef::MakeIndexNoCheck(a_BlockX, a_BlockY, a_BlockZ);
|
a_BlockMeta = Chunk->GetMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
a_BlockMeta = Chunk->GetMeta(Index);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1484,9 +1481,8 @@ bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
|
|||||||
res = false;
|
res = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int idx = cChunkDef::MakeIndexNoCheck(itr->x, itr->y, itr->z);
|
itr->BlockType = Chunk->GetBlock(itr->x, itr->y, itr->z);
|
||||||
itr->BlockType = Chunk->GetBlock(idx);
|
itr->BlockMeta = Chunk->GetMeta(itr->x, itr->y, itr->z);
|
||||||
itr->BlockMeta = Chunk->GetMeta(idx);
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ChunkDef.h"
|
|
||||||
|
#include "ChunkDataCallback.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ Note that it may be called by world's BroadcastToChunk() if the client is still
|
|||||||
|
|
||||||
#include "OSSupport/IsThread.h"
|
#include "OSSupport/IsThread.h"
|
||||||
#include "ChunkDef.h"
|
#include "ChunkDef.h"
|
||||||
|
#include "ChunkDataCallback.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,9 +55,8 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = a_Chunk.MakeIndexNoCheck(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
|
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||||
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(idx);
|
NIBBLETYPE BelowMeta = a_Chunk.GetMeta(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||||
NIBBLETYPE BelowMeta = a_Chunk.GetMeta(idx);
|
|
||||||
if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta))
|
if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta))
|
||||||
{
|
{
|
||||||
// Fallen onto a block that breaks this into pickups (e. g. half-slab)
|
// Fallen onto a block that breaks this into pickups (e. g. half-slab)
|
||||||
|
@ -225,16 +225,28 @@ template class SizeChecker<UInt16, 2>;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TEST_GLOBALS
|
||||||
|
// Common headers (part 1, without macros):
|
||||||
|
#include "StringUtils.h"
|
||||||
|
#include "OSSupport/Sleep.h"
|
||||||
|
#include "OSSupport/CriticalSection.h"
|
||||||
|
#include "OSSupport/Semaphore.h"
|
||||||
|
#include "OSSupport/Event.h"
|
||||||
|
#include "OSSupport/Thread.h"
|
||||||
|
#include "OSSupport/File.h"
|
||||||
|
#include "MCLogger.h"
|
||||||
|
#else
|
||||||
|
// Logging functions
|
||||||
|
void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1,2);
|
||||||
|
|
||||||
// Common headers (part 1, without macros):
|
void inline LOGERROR(const char* a_Format, ...)
|
||||||
#include "StringUtils.h"
|
{
|
||||||
#include "OSSupport/Sleep.h"
|
va_list argList;
|
||||||
#include "OSSupport/CriticalSection.h"
|
va_start(argList, a_Format);
|
||||||
#include "OSSupport/Semaphore.h"
|
vprintf(a_Format, argList);
|
||||||
#include "OSSupport/Event.h"
|
va_end(argList);
|
||||||
#include "OSSupport/Thread.h"
|
}
|
||||||
#include "OSSupport/File.h"
|
#endif
|
||||||
#include "MCLogger.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -253,10 +265,44 @@ template class SizeChecker<UInt16, 2>;
|
|||||||
#define FAST_FLOOR_DIV( x, div ) (((x) - (((x) < 0) ? ((div) - 1) : 0)) / (div))
|
#define FAST_FLOOR_DIV( x, div ) (((x) - (((x) < 0) ? ((div) - 1) : 0)) / (div))
|
||||||
|
|
||||||
// Own version of assert() that writes failed assertions to the log for review
|
// Own version of assert() that writes failed assertions to the log for review
|
||||||
#ifdef _DEBUG
|
#ifdef TEST_GLOBALS
|
||||||
#define ASSERT( x ) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), assert(0), 0 ) )
|
|
||||||
|
class cAssertFailure
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#if (defined(_MSC_VER) && defined(_DEBUG))
|
||||||
|
#define DBG_BREAK _CrtDbgBreak()
|
||||||
|
#else
|
||||||
|
#define DBG_BREAK
|
||||||
|
#endif
|
||||||
|
#define REPORT_ERROR(FMT, ...) \
|
||||||
|
{ \
|
||||||
|
AString msg = Printf(FMT, __VA_ARGS__); \
|
||||||
|
puts(msg.c_str()); \
|
||||||
|
fflush(stdout); \
|
||||||
|
OutputDebugStringA(msg.c_str()); \
|
||||||
|
DBG_BREAK; \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define REPORT_ERROR(FMT, ...) \
|
||||||
|
{ \
|
||||||
|
AString msg = Printf(FMT, __VA_ARGS__); \
|
||||||
|
puts(msg.c_str()); \
|
||||||
|
fflush(stdout); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#define ASSERT(x) do { if (!(x)) { throw cAssertFailure();} } while (0)
|
||||||
|
#define testassert(x) do { if(!(x)) { REPORT_ERROR("Test failure: %s, file %s, line %d\n", #x, __FILE__, __LINE__); exit(1); } } while (0)
|
||||||
|
#define CheckAsserts(x) do { try {x} catch (cAssertFailure) { break; } REPORT_ERROR("Test failure: assert didn't fire for %s, file %s, line %d\n", #x, __FILE__, __LINE__); exit(1); } while (0)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define ASSERT(x) ((void)(x))
|
#ifdef _DEBUG
|
||||||
|
#define ASSERT( x ) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), assert(0), 0 ) )
|
||||||
|
#else
|
||||||
|
#define ASSERT(x) ((void)(x))
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Pretty much the same as ASSERT() but stays in Release builds
|
// Pretty much the same as ASSERT() but stays in Release builds
|
||||||
|
@ -18,20 +18,17 @@
|
|||||||
class cReader :
|
class cReader :
|
||||||
public cChunkDataCallback
|
public cChunkDataCallback
|
||||||
{
|
{
|
||||||
virtual void BlockTypes(const BLOCKTYPE * a_Type) override
|
virtual void ChunkData(const cChunkData & a_ChunkBuffer) override
|
||||||
{
|
{
|
||||||
// ROW is a block of 16 Blocks, one whole row is copied at a time (hopefully the compiler will optimize that)
|
BLOCKTYPE * OutputRows = m_BlockTypes;
|
||||||
// C++ doesn't permit copying arrays, but arrays as a part of a struct is ok :)
|
|
||||||
typedef struct {BLOCKTYPE m_Row[16]; } ROW;
|
|
||||||
ROW * InputRows = (ROW *)a_Type;
|
|
||||||
ROW * OutputRows = (ROW *)m_BlockTypes;
|
|
||||||
int InputIdx = 0;
|
int InputIdx = 0;
|
||||||
int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3;
|
int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3;
|
||||||
for (int y = 0; y < cChunkDef::Height; y++)
|
for (int y = 0; y < cChunkDef::Height; y++)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < cChunkDef::Width; z++)
|
for (int z = 0; z < cChunkDef::Width; z++)
|
||||||
{
|
{
|
||||||
OutputRows[OutputIdx] = InputRows[InputIdx++];
|
a_ChunkBuffer.CopyBlockTypes(OutputRows + OutputIdx * 16, InputIdx * 16, 16);
|
||||||
|
InputIdx++;
|
||||||
OutputIdx += 3;
|
OutputIdx += 3;
|
||||||
} // for z
|
} // for z
|
||||||
// Skip into the next y-level in the 3x3 chunk blob; each level has cChunkDef::Width * 9 rows
|
// Skip into the next y-level in the 3x3 chunk blob; each level has cChunkDef::Width * 9 rows
|
||||||
|
@ -24,7 +24,7 @@ void cMobProximityCounter::CollectMob(cEntity& a_Monster, cChunk& a_Chunk, doubl
|
|||||||
if (a_Distance < it->second.m_Distance)
|
if (a_Distance < it->second.m_Distance)
|
||||||
{
|
{
|
||||||
it->second.m_Distance = a_Distance;
|
it->second.m_Distance = a_Distance;
|
||||||
it->second.m_Chunk = a_Chunk;
|
it->second.m_Chunk = &a_Chunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ void cMobProximityCounter::convertMaps()
|
|||||||
{
|
{
|
||||||
for(tMonsterToDistance::const_iterator itr = m_MonsterToDistance.begin(); itr != m_MonsterToDistance.end(); ++itr)
|
for(tMonsterToDistance::const_iterator itr = m_MonsterToDistance.begin(); itr != m_MonsterToDistance.end(); ++itr)
|
||||||
{
|
{
|
||||||
m_DistanceToMonster.insert(tDistanceToMonster::value_type(itr->second.m_Distance,sMonsterAndChunk(*itr->first,itr->second.m_Chunk)));
|
m_DistanceToMonster.insert(tDistanceToMonster::value_type(itr->second.m_Distance,sMonsterAndChunk(*itr->first,*itr->second.m_Chunk)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ protected :
|
|||||||
// structs used for later maps (see m_MonsterToDistance and m_DistanceToMonster)
|
// structs used for later maps (see m_MonsterToDistance and m_DistanceToMonster)
|
||||||
struct sDistanceAndChunk
|
struct sDistanceAndChunk
|
||||||
{
|
{
|
||||||
sDistanceAndChunk(double a_Distance, cChunk& a_Chunk) : m_Distance(a_Distance), m_Chunk(a_Chunk) {}
|
sDistanceAndChunk(double a_Distance, cChunk& a_Chunk) : m_Distance(a_Distance), m_Chunk(&a_Chunk) {}
|
||||||
double m_Distance;
|
double m_Distance;
|
||||||
cChunk& m_Chunk;
|
cChunk* m_Chunk;
|
||||||
};
|
};
|
||||||
struct sMonsterAndChunk
|
struct sMonsterAndChunk
|
||||||
{
|
{
|
||||||
|
@ -95,8 +95,10 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun
|
|||||||
int NumMSecs = (int)a_Dt;
|
int NumMSecs = (int)a_Dt;
|
||||||
for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();)
|
for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();)
|
||||||
{
|
{
|
||||||
int idx = cChunkDef::MakeIndexNoCheck(itr->x, itr->y, itr->z);
|
int x = itr->x;
|
||||||
BLOCKTYPE BlockType = a_Chunk->GetBlock(idx);
|
int y = itr->y;
|
||||||
|
int z = itr->z;
|
||||||
|
BLOCKTYPE BlockType = a_Chunk->GetBlock(x,y,z);
|
||||||
|
|
||||||
if (!IsAllowedBlock(BlockType))
|
if (!IsAllowedBlock(BlockType))
|
||||||
{
|
{
|
||||||
@ -125,7 +127,7 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun
|
|||||||
itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
|
itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
NIBBLETYPE BlockMeta = a_Chunk->GetMeta(idx);
|
NIBBLETYPE BlockMeta = a_Chunk->GetMeta(x, y, z);
|
||||||
if (BlockMeta == 0x0f)
|
if (BlockMeta == 0x0f)
|
||||||
{
|
{
|
||||||
// The fire burnt out completely
|
// The fire burnt out completely
|
||||||
@ -140,7 +142,7 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun
|
|||||||
|
|
||||||
if((itr->y > 0) && (!DoesBurnForever(a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z))))
|
if((itr->y > 0) && (!DoesBurnForever(a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z))))
|
||||||
{
|
{
|
||||||
a_Chunk->SetMeta(idx, BlockMeta + 1);
|
a_Chunk->SetMeta(x, y, z, BlockMeta + 1);
|
||||||
}
|
}
|
||||||
itr->Data = GetBurnStepTime(a_Chunk, itr->x, itr->y, itr->z); // TODO: Add some randomness into this
|
itr->Data = GetBurnStepTime(a_Chunk, itr->x, itr->y, itr->z); // TODO: Add some randomness into this
|
||||||
} // for itr - Data[]
|
} // for itr - Data[]
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::string AString;
|
typedef std::string AString;
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC)
|
#define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC)
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -727,10 +727,9 @@ void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Mineca
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cNBTChunkSerializer::LightIsValid(bool a_IsLightValid)
|
void cNBTChunkSerializer::LightIsValid(bool a_IsLightValid)
|
||||||
{
|
{
|
||||||
m_IsLightValid = a_IsLightValid;
|
m_IsLightValid = a_IsLightValid;
|
||||||
return a_IsLightValid; // We want lighting only if it's valid, otherwise don't bother
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../ChunkDef.h"
|
#include "ChunkDataCallback.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ protected:
|
|||||||
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);
|
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);
|
||||||
|
|
||||||
// cChunkDataSeparateCollector overrides:
|
// cChunkDataSeparateCollector overrides:
|
||||||
virtual bool LightIsValid(bool a_IsLightValid) override;
|
virtual void LightIsValid(bool a_IsLightValid) override;
|
||||||
virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) override;
|
virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) override;
|
||||||
virtual void Entity(cEntity * a_Entity) override;
|
virtual void Entity(cEntity * a_Entity) override;
|
||||||
virtual void BlockEntity(cBlockEntity * a_Entity) override;
|
virtual void BlockEntity(cBlockEntity * a_Entity) override;
|
||||||
|
@ -107,15 +107,13 @@ void cJsonChunkSerializer::BlockEntity(cBlockEntity * a_BlockEntity)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cJsonChunkSerializer::LightIsValid(bool a_IsLightValid)
|
void cJsonChunkSerializer::LightIsValid(bool a_IsLightValid)
|
||||||
{
|
{
|
||||||
if (!a_IsLightValid)
|
if (a_IsLightValid)
|
||||||
{
|
{
|
||||||
return false;
|
m_Root["IsLightValid"] = true;
|
||||||
|
m_HasJsonData = true;
|
||||||
}
|
}
|
||||||
m_Root["IsLightValid"] = true;
|
|
||||||
m_HasJsonData = true;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "WorldStorage.h"
|
#include "WorldStorage.h"
|
||||||
#include "../Vector3.h"
|
#include "../Vector3.h"
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include "ChunkDataCallback.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -21,7 +22,7 @@
|
|||||||
|
|
||||||
/// Helper class for serializing a chunk into Json
|
/// Helper class for serializing a chunk into Json
|
||||||
class cJsonChunkSerializer :
|
class cJsonChunkSerializer :
|
||||||
public cChunkDataCollector
|
public cChunkDataArrayCollector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ protected:
|
|||||||
// cChunkDataCollector overrides:
|
// cChunkDataCollector overrides:
|
||||||
virtual void Entity (cEntity * a_Entity) override;
|
virtual void Entity (cEntity * a_Entity) override;
|
||||||
virtual void BlockEntity (cBlockEntity * a_Entity) override;
|
virtual void BlockEntity (cBlockEntity * a_Entity) override;
|
||||||
virtual bool LightIsValid (bool a_IsLightValid) override;
|
virtual void LightIsValid (bool a_IsLightValid) override;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
7
tests/CMakeLists.txt
Normal file
7
tests/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required (VERSION 2.6)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
add_subdirectory(ChunkData)
|
89
tests/ChunkData/ArraytoCoord.cpp
Normal file
89
tests/ChunkData/ArraytoCoord.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// Test first segment
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
BLOCKTYPE SrcBlockBuffer[16 * 16 * 256];
|
||||||
|
memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer));
|
||||||
|
SrcBlockBuffer[7 + (4 * 16) + (5 * 16 * 16)] = 0xcd;
|
||||||
|
buffer.SetBlockTypes(SrcBlockBuffer);
|
||||||
|
testassert(buffer.GetBlock(7, 5, 4) == 0xcd);
|
||||||
|
|
||||||
|
NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer));
|
||||||
|
SrcNibbleBuffer[(6 + (1 * 16) + (2 * 16 * 16)) / 2] = 0xe;
|
||||||
|
buffer.SetMetas(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetMeta(6, 2, 1) == 0xe);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer));
|
||||||
|
SrcNibbleBuffer[(6 + (1 * 16) + (2 * 16 * 16)) / 2] = 0xe;
|
||||||
|
buffer.SetBlockLight(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetBlockLight(6, 2, 1) == 0xe);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer));
|
||||||
|
SrcNibbleBuffer[(6 + (1 * 16) + (2 * 16 * 16)) / 2] = 0xe;
|
||||||
|
buffer.SetSkyLight(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetSkyLight(6, 2, 1) == 0xe);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// test following segment
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
BLOCKTYPE SrcBlockBuffer[16 * 16 * 256];
|
||||||
|
memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer));
|
||||||
|
SrcBlockBuffer[7 + (4 * 16) + (24 * 16 * 16)] = 0xcd;
|
||||||
|
buffer.SetBlockTypes(SrcBlockBuffer);
|
||||||
|
testassert(buffer.GetBlock(7, 24, 4) == 0xcd);
|
||||||
|
|
||||||
|
NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer));
|
||||||
|
SrcNibbleBuffer[(6 + (1 * 16) + (24 * 16 * 16)) / 2] = 0xe;
|
||||||
|
buffer.SetMetas(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetMeta(6, 24, 1) == 0xe);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer));
|
||||||
|
SrcNibbleBuffer[(6 + 1 * 16 + 24 * 16 * 16) / 2] = 0xe;
|
||||||
|
buffer.SetBlockLight(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetBlockLight(6, 24, 1) == 0xe);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0xff, sizeof(SrcNibbleBuffer));
|
||||||
|
SrcNibbleBuffer[(6 + (1 * 16) + (24 * 16 * 16)) / 2] = 0xe;
|
||||||
|
buffer.SetSkyLight(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetSkyLight(6, 24, 1) == 0xe);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// test zeros
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
BLOCKTYPE SrcBlockBuffer[16 * 16 * 256];
|
||||||
|
memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer));
|
||||||
|
buffer.SetBlockTypes(SrcBlockBuffer);
|
||||||
|
testassert(buffer.GetBlock(7, 24, 4) == 0x00);
|
||||||
|
|
||||||
|
NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer));
|
||||||
|
buffer.SetMetas(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetMeta(6, 24, 1) == 0x0);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer));
|
||||||
|
buffer.SetBlockLight(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetBlockLight(6, 24, 1) == 0x0);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0xff, sizeof(SrcNibbleBuffer));
|
||||||
|
buffer.SetSkyLight(SrcNibbleBuffer);
|
||||||
|
testassert(buffer.GetSkyLight(6, 24, 1) == 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All tests passed:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
29
tests/ChunkData/CMakeLists.txt
Normal file
29
tests/ChunkData/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
cmake_minimum_required (VERSION 2.6)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/)
|
||||||
|
|
||||||
|
add_definitions(-DTEST_GLOBALS=1)
|
||||||
|
add_library(ChunkBuffer ${CMAKE_SOURCE_DIR}/src/ChunkData.cpp ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(creatable-exe creatable.cpp)
|
||||||
|
target_link_libraries(creatable-exe ChunkBuffer)
|
||||||
|
add_test(NAME creatable-test COMMAND creatable-exe)
|
||||||
|
|
||||||
|
add_executable(coordinates-exe Coordinates.cpp)
|
||||||
|
target_link_libraries(coordinates-exe ChunkBuffer)
|
||||||
|
add_test(NAME coordinates-test COMMAND coordinates-exe)
|
||||||
|
|
||||||
|
add_executable(copies-exe Copies.cpp)
|
||||||
|
target_link_libraries(copies-exe ChunkBuffer)
|
||||||
|
add_test(NAME copies-test COMMAND copies-exe)
|
||||||
|
|
||||||
|
add_executable(arraystocoords-exe ArraytoCoord.cpp)
|
||||||
|
target_link_libraries(arraystocoords-exe ChunkBuffer)
|
||||||
|
add_test(NAME arraystocoords-test COMMAND arraystocoords-exe)
|
||||||
|
|
||||||
|
add_executable(copyblocks-exe CopyBlocks.cpp)
|
||||||
|
target_link_libraries(copyblocks-exe ChunkBuffer)
|
||||||
|
add_test(NAME copyblocks-test COMMAND copyblocks-exe)
|
143
tests/ChunkData/Coordinates.cpp
Normal file
143
tests/ChunkData/Coordinates.cpp
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
// Empty chunks
|
||||||
|
buffer.SetBlock(0, 0, 0, 0xAB);
|
||||||
|
testassert(buffer.GetBlock(0, 0, 0) == 0xAB);
|
||||||
|
buffer.SetMeta(0, 16, 0, 0xC);
|
||||||
|
testassert(buffer.GetMeta(0, 16, 0) == 0xC);
|
||||||
|
|
||||||
|
// loaded but not written segments
|
||||||
|
testassert(buffer.GetBlock(1, 0, 0) == 0x0);
|
||||||
|
testassert(buffer.GetMeta(1, 16, 0) == 0x0);
|
||||||
|
|
||||||
|
// Notloaded segments
|
||||||
|
testassert(buffer.GetBlock(0, 32, 0) == 0x0);
|
||||||
|
testassert(buffer.GetMeta(0, 48, 0) == 0x0);
|
||||||
|
|
||||||
|
// Out of Range
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetBlock(-1, 0, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetBlock(0, -1, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetBlock(0, 0, -1, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetBlock(256, 0, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetBlock(0, 256, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetBlock(0, 0, 256, 0);
|
||||||
|
);
|
||||||
|
|
||||||
|
// Out of Range
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetBlock(-1, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetBlock(0, -1, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetBlock(0, 0, -1);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetBlock(256, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetBlock(0, 256, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetBlock(0, 0, 256);
|
||||||
|
);
|
||||||
|
|
||||||
|
// Out of Range
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetMeta(-1, 0, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetMeta(0, -1, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetMeta(0, 0, -1, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetMeta(256, 0, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetMeta(0, 256, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.SetMeta(0, 0, 256, 0);
|
||||||
|
);
|
||||||
|
|
||||||
|
// Out of Range
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetMeta(-1, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetMeta(0, -1, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetMeta(0, 0, -1);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetMeta(256, 0, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetMeta(0, 256, 0);
|
||||||
|
);
|
||||||
|
CheckAsserts(
|
||||||
|
buffer.GetMeta(0, 0, 256);
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
// Zero's
|
||||||
|
buffer.SetBlock(0, 0, 0, 0x0);
|
||||||
|
buffer.SetBlock(0, 0, 1, 0xab);
|
||||||
|
testassert(buffer.GetBlock(0, 0, 0) == 0x0);
|
||||||
|
testassert(buffer.GetBlock(0, 0, 1) == 0xab);
|
||||||
|
|
||||||
|
buffer.SetMeta(0, 16, 0, 0x0);
|
||||||
|
buffer.SetMeta(0, 16, 1, 0xc);
|
||||||
|
testassert(buffer.GetMeta(0, 16, 0) == 0x0);
|
||||||
|
testassert(buffer.GetMeta(0, 16, 1) == 0xc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// Operator =
|
||||||
|
cChunkData buffer;
|
||||||
|
buffer.SetBlock(0, 0, 0, 0x42);
|
||||||
|
cChunkData copy;
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
copy = buffer;
|
||||||
|
#else
|
||||||
|
copy = std::move(buffer);
|
||||||
|
#endif
|
||||||
|
testassert(copy.GetBlock(0, 0, 0) == 0x42);
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
copy = copy;
|
||||||
|
#else
|
||||||
|
copy = std::move(copy);
|
||||||
|
#endif
|
||||||
|
testassert(copy.GetBlock(0, 0, 0) == 0x42);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
134
tests/ChunkData/Copies.cpp
Normal file
134
tests/ChunkData/Copies.cpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
buffer.SetBlock(3, 1, 4, 0xDE);
|
||||||
|
buffer.SetMeta(3, 1, 4, 0xA);
|
||||||
|
|
||||||
|
cChunkData copy = buffer.Copy();
|
||||||
|
testassert(copy.GetBlock(3, 1, 4) == 0xDE);
|
||||||
|
testassert(copy.GetMeta(3, 1, 4) == 0xA);
|
||||||
|
|
||||||
|
BLOCKTYPE SrcBlockBuffer[16 * 16 * 256];
|
||||||
|
for (int i = 0; i < 16 * 16 * 256; i += 4)
|
||||||
|
{
|
||||||
|
SrcBlockBuffer[i + 0] = 0xde;
|
||||||
|
SrcBlockBuffer[i + 1] = 0xad;
|
||||||
|
SrcBlockBuffer[i + 2] = 0xbe;
|
||||||
|
SrcBlockBuffer[i + 3] = 0xef;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.SetBlockTypes(SrcBlockBuffer);
|
||||||
|
BLOCKTYPE DstBlockBuffer[16 * 16 * 256];
|
||||||
|
buffer.CopyBlockTypes(DstBlockBuffer);
|
||||||
|
testassert(memcmp(SrcBlockBuffer, DstBlockBuffer, (16 * 16 * 256) - 1) == 0);
|
||||||
|
|
||||||
|
memset(SrcBlockBuffer, 0x00, 16 * 16 * 256);
|
||||||
|
buffer.SetBlockTypes(SrcBlockBuffer);
|
||||||
|
buffer.CopyBlockTypes(DstBlockBuffer);
|
||||||
|
testassert(memcmp(SrcBlockBuffer, DstBlockBuffer, (16 * 16 * 256) - 1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
for (int i = 0; i < 16 * 16 * 256 / 2; i += 4)
|
||||||
|
{
|
||||||
|
SrcNibbleBuffer[i + 0] = 0xde;
|
||||||
|
SrcNibbleBuffer[i + 1] = 0xad;
|
||||||
|
SrcNibbleBuffer[i + 2] = 0xbe;
|
||||||
|
SrcNibbleBuffer[i + 3] = 0xef;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.SetMetas(SrcNibbleBuffer);
|
||||||
|
NIBBLETYPE DstNibbleBuffer[16 * 16 * 256/ 2];
|
||||||
|
buffer.CopyMetas(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 /2);
|
||||||
|
buffer.SetMetas(SrcNibbleBuffer);
|
||||||
|
buffer.CopyMetas(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
for (int i = 0; i < 16 * 16 * 256 / 2; i += 4)
|
||||||
|
{
|
||||||
|
SrcNibbleBuffer[i + 0] = 0xde;
|
||||||
|
SrcNibbleBuffer[i + 1] = 0xad;
|
||||||
|
SrcNibbleBuffer[i + 2] = 0xbe;
|
||||||
|
SrcNibbleBuffer[i + 3] = 0xef;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.SetBlockLight(SrcNibbleBuffer);
|
||||||
|
NIBBLETYPE DstNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
buffer.CopyBlockLight(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 /2) - 1) == 0);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 /2);
|
||||||
|
buffer.SetBlockLight(SrcNibbleBuffer);
|
||||||
|
buffer.CopyBlockLight(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 /2) - 1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
for (int i = 0; i < 16 * 16 * 256 / 2; i += 4)
|
||||||
|
{
|
||||||
|
SrcNibbleBuffer[i + 0] = 0xde;
|
||||||
|
SrcNibbleBuffer[i + 1] = 0xad;
|
||||||
|
SrcNibbleBuffer[i + 2] = 0xbe;
|
||||||
|
SrcNibbleBuffer[i + 3] = 0xef;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.SetSkyLight(SrcNibbleBuffer);
|
||||||
|
NIBBLETYPE DstNibbleBuffer[16 * 16 * 256/ 2];
|
||||||
|
buffer.CopySkyLight(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0xFF, 16 * 16 * 256 / 2);
|
||||||
|
buffer.SetSkyLight(SrcNibbleBuffer);
|
||||||
|
buffer.CopySkyLight(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cChunkData buffer;
|
||||||
|
|
||||||
|
BLOCKTYPE SrcBlockBuffer[16 * 16 * 256];
|
||||||
|
memset(SrcBlockBuffer, 0x00, 16 * 16 * 256);
|
||||||
|
BLOCKTYPE DstBlockBuffer[16 * 16 * 256];
|
||||||
|
buffer.CopyBlockTypes(DstBlockBuffer);
|
||||||
|
testassert(memcmp(SrcBlockBuffer, DstBlockBuffer, (16 * 16 * 256) - 1) == 0);
|
||||||
|
|
||||||
|
NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 / 2);
|
||||||
|
NIBBLETYPE DstNibbleBuffer[16 * 16 * 256 / 2];
|
||||||
|
buffer.CopyMetas(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 / 2);
|
||||||
|
buffer.CopyBlockLight(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0);
|
||||||
|
|
||||||
|
memset(SrcNibbleBuffer, 0xFF, 16 * 16 * 256 / 2);
|
||||||
|
buffer.CopySkyLight(DstNibbleBuffer);
|
||||||
|
testassert(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All tests successful:
|
||||||
|
return 0;
|
||||||
|
}
|
76
tests/ChunkData/CopyBlocks.cpp
Normal file
76
tests/ChunkData/CopyBlocks.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
// CopyBlocks.cpp
|
||||||
|
|
||||||
|
// Implements the test for cChunkData::CopyBlockTypes() range copying
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
// Set up a cChunkData with known contents - all blocks 0x01, all metas 0x02:
|
||||||
|
cChunkData Data;
|
||||||
|
cChunkDef::BlockTypes BlockTypes;
|
||||||
|
cChunkDef::BlockNibbles BlockMetas;
|
||||||
|
memset(BlockTypes, 0x01, sizeof(BlockTypes));
|
||||||
|
memset(BlockMetas, 0x02, sizeof(BlockMetas));
|
||||||
|
Data.SetBlockTypes(BlockTypes);
|
||||||
|
Data.SetMetas(BlockMetas);
|
||||||
|
|
||||||
|
// Try to read varying amounts of blocktypes from the cChunkData.
|
||||||
|
// Verify that the exact amount of memory is copied, by copying to a larger buffer and checking its boundaries
|
||||||
|
BLOCKTYPE TestBuffer[5 * cChunkDef::NumBlocks];
|
||||||
|
size_t WritePosIdx = 2 * cChunkDef::NumBlocks;
|
||||||
|
BLOCKTYPE * WritePosition = &TestBuffer[WritePosIdx];
|
||||||
|
memset(TestBuffer, 0x03, sizeof(TestBuffer));
|
||||||
|
size_t LastReportedStep = 1;
|
||||||
|
for (size_t idx = 0; idx < 5000; idx += 7)
|
||||||
|
{
|
||||||
|
if (idx / 500 != LastReportedStep)
|
||||||
|
{
|
||||||
|
printf("Testing index %u...\n", (unsigned)idx);
|
||||||
|
LastReportedStep = idx / 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t len = 3; len < 1000; len += 13)
|
||||||
|
{
|
||||||
|
Data.CopyBlockTypes(WritePosition, idx, len);
|
||||||
|
|
||||||
|
// Verify the data copied:
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
assert_test(WritePosition[i] == 0x01);
|
||||||
|
}
|
||||||
|
// Verify the space before the copied data hasn't been changed:
|
||||||
|
for (size_t i = 0; i < WritePosIdx; i++)
|
||||||
|
{
|
||||||
|
assert_test(TestBuffer[i] == 0x03);
|
||||||
|
}
|
||||||
|
// Verify the space after the copied data hasn't been changed:
|
||||||
|
for (size_t i = WritePosIdx + idx + len; i < ARRAYCOUNT(TestBuffer); i++)
|
||||||
|
{
|
||||||
|
assert_test(TestBuffer[i] == 0x03);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-initialize the buffer for the next test:
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
WritePosition[i] = 0x03;
|
||||||
|
}
|
||||||
|
} // for len
|
||||||
|
} // for idx
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
9
tests/ChunkData/creatable.cpp
Normal file
9
tests/ChunkData/creatable.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ChunkData.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
cChunkData buffer;
|
||||||
|
return 0;
|
||||||
|
}
|
9
uploadCoverage.sh
Executable file
9
uploadCoverage.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ "$TRAVIS_MCSERVER_BUILD_TYPE" == "COVERAGE" ]
|
||||||
|
then
|
||||||
|
find tests -type f -name '*.gcda' -exec sh -c 'cp {} $(dirname {})/../$(basename {})' \;
|
||||||
|
coveralls --exclude lib --exclude Android >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user