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/
|
||||
cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
CTestTestfile.cmake
|
||||
Makefile
|
||||
|
||||
*.a
|
||||
|
14
.travis.yml
14
.travis.yml
@ -2,8 +2,15 @@ language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_MCSERVER_BUILD_TYPE" == "COVERAGE" ]; then sudo pip install cpp_coveralls; fi
|
||||
|
||||
# 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:
|
||||
- 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=DEBUG TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer_debug
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: TRAVIS_MCSERVER_BUILD_TYPE=COVERAGE MCSERVER_PATH=./MCServer
|
||||
|
||||
# Notification Settings
|
||||
notifications:
|
||||
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 )
|
||||
enable_language(CXX C)
|
||||
@ -14,6 +14,10 @@ if(DEFINED ENV{TRAVIS_MCSERVER_FORCE32})
|
||||
set(FORCE32 $ENV{TRAVIS_MCSERVER_FORCE32})
|
||||
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.
|
||||
if(${BUILD_TOOLS})
|
||||
add_subdirectory(Tools/MCADefrag/)
|
||||
@ -69,3 +73,8 @@ set_exe_flags()
|
||||
|
||||
add_subdirectory (src)
|
||||
|
||||
if(${SELF_TEST})
|
||||
enable_testing()
|
||||
add_subdirectory (tests)
|
||||
endif()
|
||||
|
||||
|
@ -1,32 +1,41 @@
|
||||
macro (add_flags_lnk 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_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_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_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${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_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_COVERAGE} ${FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_COVERAGE} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_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()
|
||||
|
||||
macro(add_flags_cxx FLAGS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_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_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} ${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()
|
||||
|
||||
|
||||
macro(set_flags)
|
||||
# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/cmake-coverage/")
|
||||
include(CodeCoverage)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
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()
|
||||
|
||||
if(MSVC)
|
||||
@ -42,9 +51,10 @@ macro(set_flags)
|
||||
elseif(APPLE)
|
||||
#on os x clang adds pthread for us but we need to add it for gcc
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
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_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -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_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_lnk("-stdlib=libc++")
|
||||
else()
|
||||
@ -57,6 +67,7 @@ macro(set_flags)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
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_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
||||
endif()
|
||||
|
||||
@ -97,10 +108,12 @@ macro(set_lib_flags)
|
||||
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_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_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_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_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()
|
||||
|
||||
# On Unix we use two dynamic loading libraries dl and ltdl.
|
||||
@ -128,7 +141,7 @@ macro(enable_profile)
|
||||
|
||||
# Declare the profiling configurations:
|
||||
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."
|
||||
FORCE )
|
||||
SET(CMAKE_C_FLAGS_DEBUGPROFILE
|
||||
@ -171,7 +184,11 @@ macro(enable_profile)
|
||||
CMAKE_EXE_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
|
||||
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()
|
||||
|
||||
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;
|
||||
# the important warnings are turned on using #pragma in Globals.h
|
||||
if (NOT MSVC)
|
||||
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_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
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_CXX_FLAGS_DEBUG "${CMAKE_CXX_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")
|
||||
|
||||
# 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)
|
||||
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()
|
||||
|
@ -10,7 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
|
||||
// tolua_begin
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "OSSupport/GZipFile.h"
|
||||
#include "Blocks/BlockHandler.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
|
||||
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++)
|
||||
if (m_Area.m_BlockTypes != NULL)
|
||||
{
|
||||
int ChunkZ = BaseZ + z;
|
||||
int AreaZ = OffZ + z;
|
||||
for (int x = 0; x < SizeX; x++)
|
||||
int SizeY = m_Area.m_Size.y;
|
||||
int MinY = m_Origin.y;
|
||||
|
||||
// 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;
|
||||
int AreaX = OffX + x;
|
||||
m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = cChunkDef::GetBlock(a_BlockTypes, ChunkX, ChunkY, ChunkZ);
|
||||
} // for x
|
||||
} // for z
|
||||
} // for y
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cBlockArea::cChunkReader::BlockMeta(const NIBBLETYPE * a_BlockMetas)
|
||||
{
|
||||
if (m_Area.m_BlockMetas == NULL)
|
||||
{
|
||||
// Don't want metas
|
||||
return;
|
||||
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 AreaZ = OffZ + z;
|
||||
for (int x = 0; x < SizeX; x++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cBlockArea::cChunkReader::BlockLight(const NIBBLETYPE * a_BlockLight)
|
||||
{
|
||||
if (m_Area.m_BlockLight == NULL)
|
||||
if (m_Area.m_BlockMetas != NULL)
|
||||
{
|
||||
// Don't want light
|
||||
return;
|
||||
a_BlockBuffer.CopyMetas(m_Area.m_BlockMetas);
|
||||
}
|
||||
CopyNibbles(m_Area.m_BlockLight, a_BlockLight);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cBlockArea::cChunkReader::BlockSkyLight(const NIBBLETYPE * a_BlockSkyLight)
|
||||
{
|
||||
if (m_Area.m_BlockSkyLight == NULL)
|
||||
if (m_Area.m_BlockLight != NULL)
|
||||
{
|
||||
// Don't want skylight
|
||||
return;
|
||||
a_BlockBuffer.CopyBlockLight(m_Area.m_BlockLight);
|
||||
}
|
||||
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 "Vector3.h"
|
||||
#include "ChunkDataCallback.h"
|
||||
|
||||
|
||||
|
||||
@ -316,11 +317,8 @@ protected:
|
||||
void CopyNibbles(NIBBLETYPE * a_AreaDst, const NIBBLETYPE * a_ChunkSrc);
|
||||
|
||||
// cChunkDataCallback overrides:
|
||||
virtual bool Coords (int a_ChunkX, int a_ChunkZ) override;
|
||||
virtual void BlockTypes (const BLOCKTYPE * 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;
|
||||
virtual bool Coords(int a_ChunkX, int a_ChunkZ) override;
|
||||
virtual void ChunkData(const cChunkData & a_BlockTypes) override;
|
||||
} ;
|
||||
|
||||
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)
|
||||
{
|
||||
a_Callback.HeightMap (&m_HeightMap);
|
||||
a_Callback.BiomeData (&m_BiomeMap);
|
||||
a_Callback.HeightMap(&m_HeightMap);
|
||||
a_Callback.BiomeData(&m_BiomeMap);
|
||||
|
||||
COMPRESSED_BLOCKTYPE Blocks = m_BlockTypes;
|
||||
Blocks.resize(NumBlocks);
|
||||
a_Callback.BlockTypes (&Blocks[0]);
|
||||
a_Callback.LightIsValid(m_IsLightValid);
|
||||
|
||||
COMPRESSED_NIBBLETYPE Metas = m_BlockMeta;
|
||||
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]);
|
||||
a_Callback.ChunkData(m_ChunkData);
|
||||
|
||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
||||
{
|
||||
@ -296,48 +282,10 @@ void cChunk::SetAllData(
|
||||
CalculateHeightmap(a_BlockTypes);
|
||||
}
|
||||
|
||||
int IdxWhereNonEmptyStarts = 0;
|
||||
{ // Blocktype compression
|
||||
unsigned char Highest = 0;
|
||||
int X = 0, Z = 0;
|
||||
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_ChunkData.SetBlockTypes(a_BlockTypes);
|
||||
m_ChunkData.SetMetas(a_BlockMeta);
|
||||
m_ChunkData.SetBlockLight(a_BlockLight);
|
||||
m_ChunkData.SetSkyLight(a_BlockSkyLight);
|
||||
|
||||
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.
|
||||
// Postponing until we see how bad it is :)
|
||||
|
||||
{ // Compress blocklight
|
||||
m_BlockLight.clear();
|
||||
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[m_BlockTypes.size() / 2]);
|
||||
}
|
||||
m_ChunkData.SetBlockLight(a_BlockLight);
|
||||
|
||||
{ // Compress skylight
|
||||
m_BlockSkyLight.clear();
|
||||
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_SkyLight[0], &a_SkyLight[m_BlockTypes.size() / 2]);
|
||||
}
|
||||
m_ChunkData.SetSkyLight(a_SkyLight);
|
||||
|
||||
m_IsLightValid = true;
|
||||
}
|
||||
@ -397,8 +339,7 @@ void cChunk::SetLight(
|
||||
|
||||
void cChunk::GetBlockTypes(BLOCKTYPE * a_BlockTypes)
|
||||
{
|
||||
std::copy(m_BlockTypes.begin(), m_BlockTypes.end(), a_BlockTypes);
|
||||
std::fill_n(&a_BlockTypes[m_BlockTypes.size()], NumBlocks - m_BlockTypes.size(), E_BLOCK_AIR);
|
||||
m_ChunkData.CopyBlockTypes(a_BlockTypes);
|
||||
}
|
||||
|
||||
|
||||
@ -684,8 +625,7 @@ void cChunk::Tick(float a_Dt)
|
||||
|
||||
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(Index));
|
||||
cBlockHandler * Handler = BlockHandler(GetBlock(a_RelX, a_RelY, a_RelZ));
|
||||
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
||||
cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap());
|
||||
cBlockInServerPluginInterface PluginInterface(*this->GetWorld());
|
||||
@ -810,19 +750,18 @@ void cChunk::CheckBlocks()
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::vector<unsigned int> ToTickBlocks;
|
||||
std::vector<Vector3i> ToTickBlocks;
|
||||
std::swap(m_ToTickBlocks, ToTickBlocks);
|
||||
|
||||
cChunkInterface ChunkInterface(m_World->GetChunkMap());
|
||||
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 BlockPos = IndexToCoordinate(index);
|
||||
Vector3i Pos = (*itr);
|
||||
|
||||
cBlockHandler * Handler = BlockHandler(GetBlock(index));
|
||||
Handler->Check(ChunkInterface, PluginInterface, BlockPos.x, BlockPos.y, BlockPos.z, *this);
|
||||
cBlockHandler * Handler = BlockHandler(GetBlock(Pos));
|
||||
Handler->Check(ChunkInterface, PluginInterface, Pos.x, Pos.y, Pos.z, *this);
|
||||
} // for itr - ToTickBlocks[]
|
||||
}
|
||||
|
||||
@ -865,8 +804,7 @@ void cChunk::TickBlocks(void)
|
||||
continue; // It's all air up here
|
||||
}
|
||||
|
||||
unsigned int Index = MakeIndexNoCheck(m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
||||
cBlockHandler * Handler = BlockHandler(GetBlock(Index));
|
||||
cBlockHandler * Handler = BlockHandler(GetBlock(m_BlockTickX, m_BlockTickY, m_BlockTickZ));
|
||||
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
|
||||
Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface, *this, m_BlockTickX, m_BlockTickY, m_BlockTickZ);
|
||||
} // 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
|
||||
return false;
|
||||
}
|
||||
int idx = Chunk->MakeIndex(a_RelX, a_RelY, a_RelZ);
|
||||
a_BlockLight = Chunk->GetBlockLight(idx);
|
||||
a_SkyLight = Chunk->GetSkyLight(idx);
|
||||
a_BlockLight = Chunk->GetBlockLight(a_RelX, a_RelY, a_RelZ);
|
||||
a_SkyLight = Chunk->GetSkyLight(a_RelX, a_RelY, a_RelZ);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1465,11 +1402,9 @@ void cChunk::CalculateHeightmap(const BLOCKTYPE * a_BlockTypes)
|
||||
void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE 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:
|
||||
m_ToTickBlocks.push_back(index);
|
||||
m_ToTickBlocks.push_back(Vector3i(a_RelX, a_RelY, a_RelZ));
|
||||
QueueTickBlockNeighbors(a_RelX, a_RelY, a_RelZ);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
const int index = MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
||||
const BLOCKTYPE OldBlockType = GetBlock(index);
|
||||
const BLOCKTYPE OldBlockMeta = GetNibble(m_BlockMeta, index);
|
||||
const BLOCKTYPE OldBlockType = GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||
const BLOCKTYPE OldBlockMeta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta))
|
||||
{
|
||||
return;
|
||||
@ -1581,11 +1515,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
||||
|
||||
MarkDirty();
|
||||
|
||||
if ((size_t)index >= m_BlockTypes.size())
|
||||
{
|
||||
m_BlockTypes.resize(index + 1);
|
||||
}
|
||||
m_BlockTypes[index] = a_BlockType;
|
||||
m_ChunkData.SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType);
|
||||
|
||||
// The client doesn't need to distinguish between stationary and nonstationary fluids:
|
||||
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));
|
||||
}
|
||||
|
||||
SetNibble(m_BlockMeta, index, a_BlockMeta);
|
||||
m_ChunkData.SetMeta(a_RelX, a_RelY, a_RelZ, a_BlockMeta);
|
||||
|
||||
// ONLY recalculate lighting if it's necessary!
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
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:
|
||||
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 GetBlock(MakeIndexNoCheck(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];
|
||||
return m_ChunkData.GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
||||
a_BlockType = GetBlock(Idx);
|
||||
a_BlockMeta = cChunkDef::GetNibble(m_BlockMeta, Idx);
|
||||
a_BlockType = GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||
a_BlockMeta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
int Idx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
|
||||
a_BlockType = GetBlock(Idx);
|
||||
a_Meta = cChunkDef::GetNibble(m_BlockMeta, Idx);
|
||||
a_SkyLight = cChunkDef::GetNibble(m_BlockSkyLight, Idx);
|
||||
a_BlockLight = cChunkDef::GetNibble(m_BlockLight, Idx);
|
||||
a_BlockType = GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||
a_Meta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
a_SkyLight = m_ChunkData.GetSkyLight(a_RelX, a_RelY, a_RelZ);
|
||||
a_BlockLight = m_ChunkData.GetBlockLight(a_RelX, a_RelY, a_RelZ);
|
||||
}
|
||||
|
||||
|
||||
|
37
src/Chunk.h
37
src/Chunk.h
@ -3,6 +3,7 @@
|
||||
|
||||
#include "Entities/Entity.h"
|
||||
#include "ChunkDef.h"
|
||||
#include "ChunkData.h"
|
||||
|
||||
#include "Simulator/FireSimulator.h"
|
||||
#include "Simulator/SandSimulator.h"
|
||||
@ -66,6 +67,7 @@ public:
|
||||
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
|
||||
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP // Neighbor chunks
|
||||
);
|
||||
cChunk(cChunk & other);
|
||||
~cChunk();
|
||||
|
||||
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.
|
||||
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 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;
|
||||
}
|
||||
|
||||
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_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); }
|
||||
void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta);
|
||||
inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
|
||||
{
|
||||
return m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
}
|
||||
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();
|
||||
|
||||
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 GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockLight, a_RelX, a_RelY, a_RelZ); }
|
||||
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 */
|
||||
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_HasLoadFailed; // True if chunk failed to load and hasn't been generated yet since then
|
||||
|
||||
std::vector<unsigned int> m_ToTickBlocks;
|
||||
sSetBlockVector m_PendingSendBlocks; ///< Blocks that have changed and need to be sent to all clients
|
||||
std::vector<Vector3i> m_ToTickBlocks;
|
||||
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
|
||||
|
||||
@ -420,10 +430,7 @@ private:
|
||||
cWorld * m_World;
|
||||
cChunkMap * m_ChunkMap;
|
||||
|
||||
COMPRESSED_BLOCKTYPE m_BlockTypes;
|
||||
COMPRESSED_NIBBLETYPE m_BlockMeta;
|
||||
COMPRESSED_NIBBLETYPE m_BlockLight;
|
||||
COMPRESSED_NIBBLETYPE m_BlockSkyLight;
|
||||
cChunkData m_ChunkData;
|
||||
|
||||
cChunkDef::HeightMap m_HeightMap;
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
int Index = cChunkDef::MakeIndexNoCheck(a_BlockX, a_BlockY, a_BlockZ);
|
||||
a_BlockType = Chunk->GetBlock(Index);
|
||||
a_BlockMeta = Chunk->GetMeta(Index);
|
||||
a_BlockType = Chunk->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||
a_BlockMeta = Chunk->GetMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -242,8 +241,7 @@ bool cChunkMap::LockedGetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ, BLO
|
||||
return false;
|
||||
}
|
||||
|
||||
int Index = cChunkDef::MakeIndexNoCheck(a_BlockX, a_BlockY, a_BlockZ);
|
||||
a_BlockType = Chunk->GetBlock(Index);
|
||||
a_BlockType = Chunk->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -264,8 +262,7 @@ bool cChunkMap::LockedGetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIB
|
||||
return false;
|
||||
}
|
||||
|
||||
int Index = cChunkDef::MakeIndexNoCheck(a_BlockX, a_BlockY, a_BlockZ);
|
||||
a_BlockMeta = Chunk->GetMeta(Index);
|
||||
a_BlockMeta = Chunk->GetMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1484,9 +1481,8 @@ bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
|
||||
res = false;
|
||||
continue;
|
||||
}
|
||||
int idx = cChunkDef::MakeIndexNoCheck(itr->x, itr->y, itr->z);
|
||||
itr->BlockType = Chunk->GetBlock(idx);
|
||||
itr->BlockMeta = Chunk->GetMeta(idx);
|
||||
itr->BlockType = Chunk->GetBlock(itr->x, itr->y, itr->z);
|
||||
itr->BlockMeta = Chunk->GetMeta(itr->x, itr->y, itr->z);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -5,7 +5,8 @@
|
||||
|
||||
#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 "ChunkDef.h"
|
||||
#include "ChunkDataCallback.h"
|
||||
|
||||
|
||||
|
||||
|
@ -55,9 +55,8 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = a_Chunk.MakeIndexNoCheck(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(idx);
|
||||
NIBBLETYPE BelowMeta = a_Chunk.GetMeta(idx);
|
||||
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||
NIBBLETYPE BelowMeta = a_Chunk.GetMeta(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||
if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta))
|
||||
{
|
||||
// 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):
|
||||
#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"
|
||||
void inline LOGERROR(const char* a_Format, ...)
|
||||
{
|
||||
va_list argList;
|
||||
va_start(argList, a_Format);
|
||||
vprintf(a_Format, argList);
|
||||
va_end(argList);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -253,10 +265,44 @@ template class SizeChecker<UInt16, 2>;
|
||||
#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
|
||||
#ifdef _DEBUG
|
||||
#define ASSERT( x ) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), assert(0), 0 ) )
|
||||
#ifdef TEST_GLOBALS
|
||||
|
||||
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
|
||||
#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
|
||||
|
||||
// Pretty much the same as ASSERT() but stays in Release builds
|
||||
|
@ -18,20 +18,17 @@
|
||||
class cReader :
|
||||
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)
|
||||
// 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;
|
||||
BLOCKTYPE * OutputRows = m_BlockTypes;
|
||||
int InputIdx = 0;
|
||||
int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3;
|
||||
for (int y = 0; y < cChunkDef::Height; y++)
|
||||
{
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
OutputRows[OutputIdx] = InputRows[InputIdx++];
|
||||
a_ChunkBuffer.CopyBlockTypes(OutputRows + OutputIdx * 16, InputIdx * 16, 16);
|
||||
InputIdx++;
|
||||
OutputIdx += 3;
|
||||
} // for z
|
||||
// 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
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;
|
||||
cChunk& m_Chunk;
|
||||
cChunk* m_Chunk;
|
||||
};
|
||||
struct sMonsterAndChunk
|
||||
{
|
||||
|
@ -95,8 +95,10 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun
|
||||
int NumMSecs = (int)a_Dt;
|
||||
for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();)
|
||||
{
|
||||
int idx = cChunkDef::MakeIndexNoCheck(itr->x, itr->y, itr->z);
|
||||
BLOCKTYPE BlockType = a_Chunk->GetBlock(idx);
|
||||
int x = itr->x;
|
||||
int y = itr->y;
|
||||
int z = itr->z;
|
||||
BLOCKTYPE BlockType = a_Chunk->GetBlock(x,y,z);
|
||||
|
||||
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
|
||||
);
|
||||
*/
|
||||
NIBBLETYPE BlockMeta = a_Chunk->GetMeta(idx);
|
||||
NIBBLETYPE BlockMeta = a_Chunk->GetMeta(x, y, z);
|
||||
if (BlockMeta == 0x0f)
|
||||
{
|
||||
// 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))))
|
||||
{
|
||||
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
|
||||
} // for itr - Data[]
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
|
||||
typedef std::string AString;
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC)
|
||||
#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;
|
||||
return a_IsLightValid; // We want lighting only if it's valid, otherwise don't bother
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../ChunkDef.h"
|
||||
#include "ChunkDataCallback.h"
|
||||
|
||||
|
||||
|
||||
@ -121,7 +121,7 @@ protected:
|
||||
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);
|
||||
|
||||
// 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 Entity(cEntity * 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 "../Vector3.h"
|
||||
#include "json/json.h"
|
||||
#include "ChunkDataCallback.h"
|
||||
|
||||
|
||||
|
||||
@ -21,7 +22,7 @@
|
||||
|
||||
/// Helper class for serializing a chunk into Json
|
||||
class cJsonChunkSerializer :
|
||||
public cChunkDataCollector
|
||||
public cChunkDataArrayCollector
|
||||
{
|
||||
public:
|
||||
|
||||
@ -42,7 +43,7 @@ protected:
|
||||
// cChunkDataCollector overrides:
|
||||
virtual void Entity (cEntity * 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…
Reference in New Issue
Block a user