BlockZapper: Initial import, can zap blocks but not entities
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1439 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
d55416a649
commit
8aa6f08959
97
Tools/BlockZapper/BlockZapper.cpp
Normal file
97
Tools/BlockZapper/BlockZapper.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
|
||||||
|
// BlockZapper.cpp
|
||||||
|
|
||||||
|
// Implements the main app entrypoint
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "Regions.h"
|
||||||
|
#include "Zapper.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// Under MSVC, link to WinSock2 (needed by FastNBT's byteswapping)
|
||||||
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ShowHelp(const char * a_ProgramFullName)
|
||||||
|
{
|
||||||
|
AString ProgramName(a_ProgramFullName);
|
||||||
|
size_t idx = ProgramName.rfind(cFile::PathSeparator);
|
||||||
|
if (idx != AString::npos)
|
||||||
|
{
|
||||||
|
ProgramName.erase(0, idx + 1);
|
||||||
|
}
|
||||||
|
printf("Tool written by _Xoft(o), code is public domain.\n");
|
||||||
|
printf("Usage:\n");
|
||||||
|
printf("%s [-w <MCAFolder>]\n", ProgramName.c_str());
|
||||||
|
printf("Zaps blocks and / or entities in specified regions.\n");
|
||||||
|
printf("Regions are read from stdin, the format is:\n");
|
||||||
|
printf(" x1 x2 y1 y2 z1 z2 [B|E|BE]\n");
|
||||||
|
printf("B or no specifier zaps blocks only\n");
|
||||||
|
printf("E zaps entities only\n");
|
||||||
|
printf("BE zaps blocks and entities\n");
|
||||||
|
printf("MCA files are searched in the <MCAFolder>; if not specified, in the current folder.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
new cMCLogger; // Create a new logger, it will assign itself as the main logger instance
|
||||||
|
|
||||||
|
AString MCAFolder = ".";
|
||||||
|
for (int i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[i], "-w") == 0)
|
||||||
|
{
|
||||||
|
if (i < argc - 1)
|
||||||
|
{
|
||||||
|
MCAFolder = argv[i + 1];
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
(strcmp(argv[i], "help") == 0) ||
|
||||||
|
(strcmp(argv[i], "-?") == 0) ||
|
||||||
|
(strcmp(argv[i], "/?") == 0) ||
|
||||||
|
(strcmp(argv[i], "-h") == 0) ||
|
||||||
|
(strcmp(argv[i], "--help") == 0)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ShowHelp(argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cRegions Regions;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// DEBUG: Read input from a file instead of stdin:
|
||||||
|
std::fstream fs("test_in.txt");
|
||||||
|
Regions.Read(fs);
|
||||||
|
//*/
|
||||||
|
|
||||||
|
Regions.Read(std::cin);
|
||||||
|
|
||||||
|
cZapper Zapper(MCAFolder);
|
||||||
|
Zapper.ZapRegions(Regions.GetAll());
|
||||||
|
|
||||||
|
LOGINFO("Done");
|
||||||
|
return 0;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
34
Tools/BlockZapper/BlockZapper.sln
Normal file
34
Tools/BlockZapper/BlockZapper.sln
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
|
# Visual C++ Express 2008
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlockZapper", "BlockZapper.vcproj", "{CE317695-CCCC-4B11-B07B-21729A110FC2}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA} = {EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\..\mc-server.clean\VC2008\zlib.vcproj", "{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release profiled|Win32 = Release profiled|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{CE317695-CCCC-4B11-B07B-21729A110FC2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{CE317695-CCCC-4B11-B07B-21729A110FC2}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{CE317695-CCCC-4B11-B07B-21729A110FC2}.Release profiled|Win32.ActiveCfg = Release|Win32
|
||||||
|
{CE317695-CCCC-4B11-B07B-21729A110FC2}.Release profiled|Win32.Build.0 = Release|Win32
|
||||||
|
{CE317695-CCCC-4B11-B07B-21729A110FC2}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{CE317695-CCCC-4B11-B07B-21729A110FC2}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Release profiled|Win32.ActiveCfg = Release profiled|Win32
|
||||||
|
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Release profiled|Win32.Build.0 = Release profiled|Win32
|
||||||
|
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
19
Tools/BlockZapper/BlockZapper.txt
Normal file
19
Tools/BlockZapper/BlockZapper.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
// BlockZapper.txt
|
||||||
|
|
||||||
|
/*
|
||||||
|
This project implements a simple tool that can "zap" blocks out of an Anvil-stored MineCraft world.
|
||||||
|
It is usually used by server admins when their servers fail with a bug and store an invalid block in the world.
|
||||||
|
This tool takes a coord triplet and a radius triplet and replaces all blocks within the (new york-metric) radius of the coords with air.
|
||||||
|
The triplets pair is given on stdin, and multiple such specifiers are allowed, each on a separate file.
|
||||||
|
If the specifier line ends with an additional " E", entities within that radius are zapped instead of blocks
|
||||||
|
If the specifier line ends with an additional " BE", both blocks and entities are zapped.
|
||||||
|
|
||||||
|
The tool is aware of extended blocktypes (256 .. 4096).
|
||||||
|
|
||||||
|
The source code for this tool is public domain, but note that it depends on a few shared sources in MCServer that may be under other licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
313
Tools/BlockZapper/BlockZapper.vcproj
Normal file
313
Tools/BlockZapper/BlockZapper.vcproj
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
<?xml version="1.0" encoding="windows-1250"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9,00"
|
||||||
|
Name="BlockZapper"
|
||||||
|
ProjectGUID="{CE317695-CCCC-4B11-B07B-21729A110FC2}"
|
||||||
|
RootNamespace="BlockZapper"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="196613"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="../../source;../../zlib-1.2.7"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
PrecompiledHeaderThrough="Globals.h"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
AdditionalIncludeDirectories="../../source;../../zlib-1.2.7"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
PrecompiledHeaderThrough="Globals.h"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\BlockZapper.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Globals.cpp"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
UsePrecompiledHeader="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Globals.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Regions.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Regions.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Zapper.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Zapper.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<Filter
|
||||||
|
Name="shared"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\Log.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\Log.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\MCLogger.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\MCLogger.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\StringCompression.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\StringCompression.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\StringUtils.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\StringUtils.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<Filter
|
||||||
|
Name="OSSupport"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\OSSupport\CriticalSection.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\OSSupport\CriticalSection.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\OSSupport\File.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\OSSupport\File.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\OSSupport\IsThread.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\OSSupport\IsThread.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\OSSupport\MakeDir.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\OSSupport\MakeDir.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="WorldStorage"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\WorldStorage\FastNBT.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\source\WorldStorage\FastNBT.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Filter>
|
||||||
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath=".\BlockZapper.txt"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
185
Tools/BlockZapper/GNUmakefile
Normal file
185
Tools/BlockZapper/GNUmakefile
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
###################################################
|
||||||
|
#
|
||||||
|
# Makefile for BlockZapper
|
||||||
|
# Creator: xoft
|
||||||
|
#
|
||||||
|
###################################################
|
||||||
|
#
|
||||||
|
# Info:
|
||||||
|
# This makefile is gnu-make spacific, other make systems needn't understand it
|
||||||
|
# This makefile generates include-file dependencies into *.d files in each build and then reuses these dependencies in the following builds
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# To make a release build, call "make"
|
||||||
|
# To make a debug build, call "make debug=1"
|
||||||
|
#
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Macros
|
||||||
|
#
|
||||||
|
|
||||||
|
CC = /usr/bin/g++
|
||||||
|
|
||||||
|
|
||||||
|
all: BlockZapper
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
# Set the variables used for compiling, based on the build mode requested:
|
||||||
|
# CC_OPTIONS ... options for the C code compiler
|
||||||
|
# CXX_OPTIONS ... options for the C++ code compiler
|
||||||
|
# LNK_OPTIONS ... options for the linker
|
||||||
|
# LNK_LIBS ... libraries to link in
|
||||||
|
# -- according to http://stackoverflow.com/questions/6183899/undefined-reference-to-dlopen, libs must come after all sources
|
||||||
|
# BUILDDIR ... folder where the intermediate object files are built
|
||||||
|
|
||||||
|
LNK_LIBS = -lstdc++ -ldl -lz
|
||||||
|
|
||||||
|
ifeq ($(debug),1)
|
||||||
|
################
|
||||||
|
# debug build - fully traceable by gdb in C++ code, slowest
|
||||||
|
# Since C code is used only for supporting libraries (zlib, lua), it is still O3-optimized
|
||||||
|
################
|
||||||
|
CC_OPTIONS = -s -ggdb -g -D_DEBUG -O3
|
||||||
|
CXX_OPTIONS = -s -ggdb -g -D_DEBUG
|
||||||
|
LNK_OPTIONS = -pthread -g -ggdb
|
||||||
|
BUILDDIR = build/debug/
|
||||||
|
|
||||||
|
else
|
||||||
|
ifeq ($(profile),1)
|
||||||
|
################
|
||||||
|
# profile build - a release build with symbols and profiling engine built in
|
||||||
|
################
|
||||||
|
CC_OPTIONS = -s -g -ggdb -O3 -pg -DNDEBUG
|
||||||
|
CXX_OPTIONS = -s -g -ggdb -O3 -pg -DNDEBUG
|
||||||
|
LNK_OPTIONS = -pthread -ggdb -O3 -pg
|
||||||
|
BUILDDIR = build/profile/
|
||||||
|
|
||||||
|
else
|
||||||
|
ifeq ($(pedantic),1)
|
||||||
|
################
|
||||||
|
# pedantic build - basically a debug build with lots of warnings
|
||||||
|
################
|
||||||
|
CC_OPTIONS = -s -g -ggdb -D_DEBUG -Wall -Wextra -pedantic -ansi -Wno-long-long
|
||||||
|
CXX_OPTIONS = -s -g -ggdb -D_DEBUG -Wall -Wextra -pedantic -ansi -Wno-long-long
|
||||||
|
LNK_OPTIONS = -pthread -ggdb
|
||||||
|
BUILDDIR = build/pedantic/
|
||||||
|
|
||||||
|
else
|
||||||
|
################
|
||||||
|
# release build - fastest run-time, no detailed gdb support
|
||||||
|
################
|
||||||
|
CC_OPTIONS = -s -g -O3 -DNDEBUG
|
||||||
|
CXX_OPTIONS = -s -g -O3 -DNDEBUG
|
||||||
|
LNK_OPTIONS = -pthread -O3
|
||||||
|
BUILDDIR = build/release/
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
################
|
||||||
|
# 32-bit build override in 64-bit build environments
|
||||||
|
# - so that BearBin doesn't need to modify his makefile after each makefile change :)
|
||||||
|
################
|
||||||
|
ifeq ($(addm32),1)
|
||||||
|
CC_OPTIONS += -m32
|
||||||
|
CXX_OPTIONS += -m32
|
||||||
|
LNK_OPTIONS += -m32
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
# INCLUDE directories
|
||||||
|
#
|
||||||
|
|
||||||
|
INCLUDE = -I.\
|
||||||
|
-I../../source\
|
||||||
|
-I../../zlib-1.2.7\
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
# Build BlockZapper
|
||||||
|
#
|
||||||
|
|
||||||
|
SOURCES := $(shell find . '(' -name '*.cpp' -o -name '*.c' ')')
|
||||||
|
|
||||||
|
SHAREDSOURCES := \
|
||||||
|
source/Log.cpp \
|
||||||
|
source/MCLogger.cpp \
|
||||||
|
source/Noise.cpp \
|
||||||
|
source/StringCompression.cpp \
|
||||||
|
source/StringUtils.cpp \
|
||||||
|
source/OSSupport/CriticalSection.cpp \
|
||||||
|
source/OSSupport/File.cpp \
|
||||||
|
source/OSSupport/IsThread.cpp \
|
||||||
|
source/OSSupport/MakeDir.cpp \
|
||||||
|
source/WorldStorage/FastNBT.cpp
|
||||||
|
|
||||||
|
SHAREDSOURCES := $(filter-out %minigzip.c,$(SHAREDSOURCES))
|
||||||
|
|
||||||
|
OBJECTS := $(patsubst %.c,$(BUILDDIR)%.o,$(SOURCES))
|
||||||
|
OBJECTS := $(patsubst %.cpp,$(BUILDDIR)%.o,$(OBJECTS))
|
||||||
|
|
||||||
|
SHAREDOBJECTS := $(patsubst %.c,$(BUILDDIR)%.o,$(SHAREDSOURCES))
|
||||||
|
SHAREDOBJECTS := $(patsubst %.cpp,$(BUILDDIR)%.o,$(SHAREDOBJECTS))
|
||||||
|
|
||||||
|
-include $(patsubst %.o,%.d,$(OBJECTS))
|
||||||
|
-include $(patsubst %.o,%.d,$(SHAREDOBJECTS))
|
||||||
|
|
||||||
|
BlockZapper : $(OBJECTS) $(SHAREDOBJECTS)
|
||||||
|
$(CC) $(LNK_OPTIONS) $(OBJECTS) $(SHAREDOBJECTS) $(LNK_LIBS) -o BlockZapper
|
||||||
|
|
||||||
|
clean :
|
||||||
|
rm -rf $(BUILDDIR) BlockZapper
|
||||||
|
|
||||||
|
install : MCServer
|
||||||
|
cp MCServer MCServer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
# Build the parts of BlockZapper
|
||||||
|
#
|
||||||
|
# options used:
|
||||||
|
# -x c ... compile as C code
|
||||||
|
# -c ... compile but do not link
|
||||||
|
# -MM ... generate a list of includes
|
||||||
|
|
||||||
|
$(BUILDDIR)%.o: %.c
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(CC_OPTIONS) -x c -c $(INCLUDE) $< -o $@
|
||||||
|
@$(CC) $(CC_OPTIONS) -x c -MM $(INCLUDE) $< > $(patsubst %.o,%.d,$@)
|
||||||
|
@mv -f $(patsubst %.o,%.d,$@) $(patsubst %.o,%.d,$@).tmp
|
||||||
|
@sed -e "s|.*:|$(BUILDDIR)$*.o:|" < $(patsubst %.o,%.d,$@).tmp > $(patsubst %.o,%.d,$@)
|
||||||
|
@sed -e 's/.*://' -e 's/\\$$//' < $(patsubst %.o,%.d,$@).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(patsubst %.o,%.d,$@)
|
||||||
|
@rm -f $(patsubst %.o,%.d,$@).tmp
|
||||||
|
|
||||||
|
$(BUILDDIR)%.o: %.cpp
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(CXX_OPTIONS) -c $(INCLUDE) $< -o $@
|
||||||
|
@$(CC) $(CXX_OPTIONS) -MM $(INCLUDE) $< > $(patsubst %.o,%.d,$@)
|
||||||
|
@mv -f $(patsubst %.o,%.d,$@) $(patsubst %.o,%.d,$@).tmp
|
||||||
|
@sed -e "s|.*:|$(BUILDDIR)$*.o:|" < $(patsubst %.o,%.d,$@).tmp > $(patsubst %.o,%.d,$@)
|
||||||
|
@sed -e 's/.*://' -e 's/\\$$//' < $(patsubst %.o,%.d,$@).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(patsubst %.o,%.d,$@)
|
||||||
|
@rm -f $(patsubst %.o,%.d,$@).tmp
|
||||||
|
|
||||||
|
$(BUILDDIR)source/%.o: ../../source/%.cpp
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(CXX_OPTIONS) -c $(INCLUDE) $< -o $@
|
||||||
|
@$(CC) $(CXX_OPTIONS) -MM $(INCLUDE) $< > $(patsubst %.o,%.d,$@)
|
||||||
|
@mv -f $(patsubst %.o,%.d,$@) $(patsubst %.o,%.d,$@).tmp
|
||||||
|
@sed -e "s|.*:|$(BUILDDIR)$*.o:|" < $(patsubst %.o,%.d,$@).tmp > $(patsubst %.o,%.d,$@)
|
||||||
|
@sed -e 's/.*://' -e 's/\\$$//' < $(patsubst %.o,%.d,$@).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(patsubst %.o,%.d,$@)
|
||||||
|
@rm -f $(patsubst %.o,%.d,$@).tmp
|
10
Tools/BlockZapper/Globals.cpp
Normal file
10
Tools/BlockZapper/Globals.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
// Globals.cpp
|
||||||
|
|
||||||
|
// Used for precompiled header generation in MSVC
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
14
Tools/BlockZapper/Globals.h
Normal file
14
Tools/BlockZapper/Globals.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
// Globals.h
|
||||||
|
|
||||||
|
// This file is used for precompiled header generation in MSVC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "../../source/Globals.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
167
Tools/BlockZapper/Regions.cpp
Normal file
167
Tools/BlockZapper/Regions.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
|
||||||
|
// Regions.cpp
|
||||||
|
|
||||||
|
// Implements the cRegions class representing the list of regions to zap
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#include "Regions.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cRegion:
|
||||||
|
|
||||||
|
cRegion::cRegion(void) :
|
||||||
|
m_MinX(0),
|
||||||
|
m_MaxX(0),
|
||||||
|
m_MinY(0),
|
||||||
|
m_MaxY(0),
|
||||||
|
m_MinZ(0),
|
||||||
|
m_MaxZ(0),
|
||||||
|
m_ShouldZapBlocks(false),
|
||||||
|
m_ShouldZapEntities(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cRegion::cRegion(int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, bool a_ShouldZapBlocks, bool a_ShouldZapEntities) :
|
||||||
|
m_MinX(a_MinX),
|
||||||
|
m_MaxX(a_MaxX),
|
||||||
|
m_MinY(std::max(0, std::min(255, a_MinY))),
|
||||||
|
m_MaxY(std::max(0, std::min(255, a_MaxY))),
|
||||||
|
m_MinZ(a_MinZ),
|
||||||
|
m_MaxZ(a_MaxZ),
|
||||||
|
m_ShouldZapBlocks(a_ShouldZapBlocks),
|
||||||
|
m_ShouldZapEntities(a_ShouldZapEntities)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cRegion::TouchesChunk(int a_ChunkX, int a_ChunkZ) const
|
||||||
|
{
|
||||||
|
int ChunkBeginX = a_ChunkX * 16;
|
||||||
|
int ChunkEndX = a_ChunkX * 16 + 15;
|
||||||
|
int ChunkBeginZ = a_ChunkZ * 16;
|
||||||
|
int ChunkEndZ = a_ChunkZ * 16 + 15;
|
||||||
|
if (
|
||||||
|
(m_MinX > ChunkEndX) || (m_MaxX < ChunkBeginX) ||
|
||||||
|
(m_MinZ > ChunkEndZ) || (m_MaxZ < ChunkBeginZ)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cRegions:
|
||||||
|
|
||||||
|
void cRegions::Read(std::istream & a_Stream)
|
||||||
|
{
|
||||||
|
while (!a_Stream.eof())
|
||||||
|
{
|
||||||
|
AString Line;
|
||||||
|
std::getline(a_Stream, Line);
|
||||||
|
|
||||||
|
// Process the line
|
||||||
|
AStringVector Split = StringSplit(Line, " \t");
|
||||||
|
AStringVector NonEmpty;
|
||||||
|
for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
if (!itr->empty())
|
||||||
|
{
|
||||||
|
NonEmpty.push_back(*itr);
|
||||||
|
}
|
||||||
|
} // for itr - Split[]
|
||||||
|
switch (NonEmpty.size())
|
||||||
|
{
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
{
|
||||||
|
AddRegion(NonEmpty);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Cannot parse line \"%s\", ignoring", Line.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cRegions::AddRegion(const AStringVector & a_Split)
|
||||||
|
{
|
||||||
|
ASSERT((a_Split.size() == 6) || (a_Split.size() == 7));
|
||||||
|
|
||||||
|
int Coords[6];
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
Coords[i] = atoi(a_Split[i].c_str());
|
||||||
|
if ((Coords[i] == 0) && (a_Split[i] != "0"))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Bad coord: \"%s\". Ignoring line.", a_Split[i].c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} // for i - a_Split[]
|
||||||
|
|
||||||
|
bool ShouldZapBlocks = true;
|
||||||
|
bool ShouldZapEntities = false;
|
||||||
|
|
||||||
|
if (a_Split.size() == 7)
|
||||||
|
{
|
||||||
|
AString Upper = a_Split[6];
|
||||||
|
StrToUpper(Upper);
|
||||||
|
if (Upper == "E")
|
||||||
|
{
|
||||||
|
ShouldZapEntities = true;
|
||||||
|
ShouldZapBlocks = false;
|
||||||
|
}
|
||||||
|
else if (Upper == "BE")
|
||||||
|
{
|
||||||
|
ShouldZapEntities = true;
|
||||||
|
}
|
||||||
|
else if (Upper == "B")
|
||||||
|
{
|
||||||
|
// Nothing needed
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Bad zap specifier: \"%s\". Ignoring line.", a_Split[6].c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap coords, if needed:
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (Coords[2 * i] > Coords[2 * i + 1])
|
||||||
|
{
|
||||||
|
std::swap(Coords[2 * i], Coords[2 * i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the region
|
||||||
|
m_Regions.push_back(cRegion(Coords[0], Coords[1], Coords[2], Coords[3], Coords[4], Coords[5], ShouldZapBlocks, ShouldZapEntities));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
58
Tools/BlockZapper/Regions.h
Normal file
58
Tools/BlockZapper/Regions.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
// Regions.h
|
||||||
|
|
||||||
|
// Declares the cRegions class representing individual regions to zap
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct cRegion
|
||||||
|
{
|
||||||
|
int m_MinX, m_MaxX;
|
||||||
|
int m_MinY, m_MaxY;
|
||||||
|
int m_MinZ, m_MaxZ;
|
||||||
|
|
||||||
|
bool m_ShouldZapBlocks;
|
||||||
|
bool m_ShouldZapEntities;
|
||||||
|
|
||||||
|
cRegion(void);
|
||||||
|
cRegion(int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, bool a_ShouldZapBlocks, bool a_ShouldZapEntities);
|
||||||
|
|
||||||
|
bool TouchesChunk(int a_ChunkX, int a_ChunkZ) const;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
typedef std::vector<cRegion> cRegionVector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cRegions
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Reads the list of regions from the specified stream
|
||||||
|
void Read(std::istream & a_Stream);
|
||||||
|
|
||||||
|
/// Returns all regions in this container
|
||||||
|
const cRegionVector & GetAll(void) const { return m_Regions; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cRegionVector m_Regions;
|
||||||
|
|
||||||
|
/// Adds a new region based on the contents of the split line. The split must already be the correct size
|
||||||
|
void AddRegion(const AStringVector & a_Split);
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
440
Tools/BlockZapper/Zapper.cpp
Normal file
440
Tools/BlockZapper/Zapper.cpp
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
|
||||||
|
// Zapper.cpp
|
||||||
|
|
||||||
|
// Implements the cZapper class representing the processor that actually zaps blocks and entities
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#include "WorldStorage/FastNBT.h"
|
||||||
|
#include "StringCompression.h"
|
||||||
|
#include "zlib.h"
|
||||||
|
|
||||||
|
#include "Zapper.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// The maximum size of an inflated chunk; raw chunk data is 192 KiB, allow 64 KiB more of entities
|
||||||
|
#define CHUNK_INFLATE_MAX 256 KiB
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cZapper::cZapper(const AString & a_MCAFolder) :
|
||||||
|
m_MCAFolder(a_MCAFolder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::ZapRegions(const cRegionVector & a_Regions)
|
||||||
|
{
|
||||||
|
for (cRegionVector::const_iterator itr = a_Regions.begin(), end = a_Regions.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
int MinAnvX, MinAnvZ;
|
||||||
|
int MaxAnvX, MaxAnvZ;
|
||||||
|
BlockToMCA(itr->m_MinX, itr->m_MinZ, MinAnvX, MinAnvZ);
|
||||||
|
BlockToMCA(itr->m_MaxX, itr->m_MaxZ, MaxAnvX, MaxAnvZ);
|
||||||
|
for (int x = MinAnvX; x <= MaxAnvX; x++)
|
||||||
|
{
|
||||||
|
for (int z = MinAnvZ; z <= MaxAnvZ; z++)
|
||||||
|
{
|
||||||
|
ZapRegionInMCAFile(*itr, x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // for itr - a_Regions
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::BlockToMCA(int a_BlockX, int a_BlockZ, int & a_MCAX, int & a_MCAZ)
|
||||||
|
{
|
||||||
|
// These need to be arithmetic shifts, consult your compiler documentation to see if it's so
|
||||||
|
// MSVC and GCC both use arithmetic shifts
|
||||||
|
a_MCAX = a_BlockX >> 10;
|
||||||
|
a_MCAZ = a_BlockZ >> 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::BlockToChunk(int a_BlockX, int a_BlockZ, int & a_ChunkX, int & a_ChunkZ)
|
||||||
|
{
|
||||||
|
// These need to be arithmetic shifts, consult your compiler documentation to see if it's so
|
||||||
|
// MSVC and GCC both use arithmetic shifts
|
||||||
|
a_ChunkX = a_BlockX >> 4;
|
||||||
|
a_ChunkZ = a_BlockZ >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::ZapRegionInMCAFile(const cRegion & a_Region, int a_MCAX, int a_MCAZ)
|
||||||
|
{
|
||||||
|
cFile fIn;
|
||||||
|
AString FileNameIn = Printf("%s/r.%d.%d.mca", m_MCAFolder.c_str(), a_MCAX, a_MCAZ);
|
||||||
|
if (!fIn.Open(FileNameIn, cFile::fmRead))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cFile fOut;
|
||||||
|
AString FileNameOut = Printf("%s/r.%d.%d.zap", m_MCAFolder.c_str(), a_MCAX, a_MCAZ);
|
||||||
|
if (!fOut.Open(FileNameOut, cFile::fmWrite))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Cannot open temporary file \"%s\" for writing, skipping file \"%s\".", FileNameOut.c_str(), FileNameIn.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AString DataOut;
|
||||||
|
DataOut.reserve(fIn.GetSize());
|
||||||
|
|
||||||
|
int HeaderIn[2048];
|
||||||
|
if (fIn.Read(HeaderIn, sizeof(HeaderIn)) != sizeof(HeaderIn))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Cannot read header from file \"%s\", skipping file.", FileNameIn.c_str());
|
||||||
|
}
|
||||||
|
int HeaderOut[2048];
|
||||||
|
for (int i = 0; i < 1024; i++)
|
||||||
|
{
|
||||||
|
if (HeaderIn[i] == 0)
|
||||||
|
{
|
||||||
|
// Chunk not present
|
||||||
|
HeaderOut[i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AString ChunkData;
|
||||||
|
int ChunkX = a_MCAX * ChunksPerMCAX + (i % ChunksPerMCAX);
|
||||||
|
int ChunkZ = a_MCAZ * ChunksPerMCAZ + (i / ChunksPerMCAX);
|
||||||
|
|
||||||
|
LoadChunkData(fIn, HeaderIn[i], ChunkData, ChunkX, ChunkZ);
|
||||||
|
|
||||||
|
if (a_Region.TouchesChunk(ChunkX, ChunkZ))
|
||||||
|
{
|
||||||
|
ZapRegionInRawChunkData(a_Region, ChunkData, ChunkX, ChunkZ);
|
||||||
|
}
|
||||||
|
unsigned char ChunkHeader[5];
|
||||||
|
size_t DataSize = ChunkData.size() + 1;
|
||||||
|
ChunkHeader[0] = (DataSize >> 24) & 0xff;
|
||||||
|
ChunkHeader[1] = (DataSize >> 16) & 0xff;
|
||||||
|
ChunkHeader[2] = (DataSize >> 8) & 0xff;
|
||||||
|
ChunkHeader[3] = DataSize & 0xff;
|
||||||
|
ChunkHeader[4] = 2; // zlib compression
|
||||||
|
size_t Alignment = 4096 - (ChunkData.size() + 5) % 4096; // 5 bytes of the header are appended outside of ChunkData
|
||||||
|
if (Alignment > 0)
|
||||||
|
{
|
||||||
|
ChunkData.append(Alignment, (char)0);
|
||||||
|
}
|
||||||
|
HeaderOut[i] = htonl(((DataOut.size() / 4096 + 2) << 8) | ((ChunkData.size() + 5) / 4096));
|
||||||
|
DataOut.append((const char *)ChunkHeader, sizeof(ChunkHeader));
|
||||||
|
DataOut.append(ChunkData);
|
||||||
|
} // for i - chunks in fIn
|
||||||
|
for (int i = 1024; i < 2048; i++)
|
||||||
|
{
|
||||||
|
HeaderOut[i] = HeaderIn[i];
|
||||||
|
}
|
||||||
|
fIn.Close();
|
||||||
|
fOut.Write(HeaderOut, sizeof(HeaderOut));
|
||||||
|
fOut.Write(DataOut.data(), DataOut.size());
|
||||||
|
fOut.Close();
|
||||||
|
cFile::Delete(FileNameIn);
|
||||||
|
cFile::Rename(FileNameOut, FileNameIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::LoadChunkData(cFile & a_InFile, int a_ChunkHeaderValue, AString & a_ChunkData, int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
a_ChunkHeaderValue = ntohl(a_ChunkHeaderValue); // Convert from big-endian to system-endian
|
||||||
|
int ChunkOffset = (a_ChunkHeaderValue >> 8) * 4096;
|
||||||
|
int ChunkSize = (a_ChunkHeaderValue & 0xff) * 4096;
|
||||||
|
a_InFile.Seek(ChunkOffset);
|
||||||
|
unsigned char ChunkHeader[5];
|
||||||
|
a_InFile.Read(ChunkHeader, sizeof(ChunkHeader));
|
||||||
|
if (ChunkHeader[4] != 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Chunk [%d, %d] is compressed in an unknown scheme (%d), skipping", a_ChunkX, a_ChunkZ, ChunkHeader[5]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int ActualSize = (ChunkHeader[0] << 24) | (ChunkHeader[1] << 16) | (ChunkHeader[2] << 8) | ChunkHeader[3];
|
||||||
|
ActualSize -= 1; // Compression took 1 byte
|
||||||
|
a_ChunkData.resize(ActualSize);
|
||||||
|
int BytesRead = a_InFile.Read((void *)(a_ChunkData.data()), ActualSize);
|
||||||
|
if (BytesRead != ActualSize)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Chunk is truncated in file (%d bytes out of %d), skipping.", BytesRead, ActualSize);
|
||||||
|
a_ChunkData.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::ZapRegionInRawChunkData(const cRegion & a_Region, AString & a_ChunkData, int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
// Decompress the data:
|
||||||
|
char Uncompressed[CHUNK_INFLATE_MAX];
|
||||||
|
z_stream strm;
|
||||||
|
strm.zalloc = (alloc_func)NULL;
|
||||||
|
strm.zfree = (free_func)NULL;
|
||||||
|
strm.opaque = NULL;
|
||||||
|
inflateInit(&strm);
|
||||||
|
strm.next_out = (Bytef *)Uncompressed;
|
||||||
|
strm.avail_out = sizeof(Uncompressed);
|
||||||
|
strm.next_in = (Bytef *)a_ChunkData.data();
|
||||||
|
strm.avail_in = a_ChunkData.size();
|
||||||
|
int res = inflate(&strm, Z_FINISH);
|
||||||
|
inflateEnd(&strm);
|
||||||
|
if (res != Z_STREAM_END)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Chunk [%d, %d] failed to decompress: error %d. Skipping chunk.", a_ChunkX, a_ChunkZ, res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// DEBUG: Output src to a file:
|
||||||
|
cFile f1;
|
||||||
|
if (f1.Open(Printf("chunk_%d_%d_in.nbt", a_ChunkX, a_ChunkZ), cFile::fmWrite))
|
||||||
|
{
|
||||||
|
f1.Write(Uncompressed, strm.total_out);
|
||||||
|
}
|
||||||
|
//*/
|
||||||
|
|
||||||
|
cParsedNBT NBT(Uncompressed, strm.total_out);
|
||||||
|
if (!NBT.IsValid())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Chunk [%d, %d] failed to parse. Skipping chunk.", a_ChunkX, a_ChunkZ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ZapRegionInNBTChunk(a_Region, NBT, a_ChunkX, a_ChunkZ);
|
||||||
|
|
||||||
|
cFastNBTWriter Writer;
|
||||||
|
for (int ch = NBT.GetFirstChild(0); ch >= 0; ch = NBT.GetNextSibling(ch))
|
||||||
|
{
|
||||||
|
SerializeNBTTag(NBT, ch, Writer);
|
||||||
|
}
|
||||||
|
Writer.Finish();
|
||||||
|
|
||||||
|
/*
|
||||||
|
// DEBUG: Output dst to a file:
|
||||||
|
cFile f2;
|
||||||
|
if (f2.Open(Printf("chunk_%d_%d_out.nbt", a_ChunkX, a_ChunkZ), cFile::fmWrite))
|
||||||
|
{
|
||||||
|
f2.Write(Writer.GetResult().data(), Writer.GetResult().size());
|
||||||
|
}
|
||||||
|
//*/
|
||||||
|
|
||||||
|
// Compress the serialized data into "Uncompressed" (reuse buffer)
|
||||||
|
CompressString(Writer.GetResult().data(), Writer.GetResult().size(), a_ChunkData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::ZapRegionInNBTChunk(const cRegion & a_Region, cParsedNBT & a_NBT, int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
int LevelTag = a_NBT.FindChildByName(a_NBT.GetRoot(), "Level");
|
||||||
|
if (LevelTag < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Cannot find Level tag in chunk [%d, %d]'s NBT. Skipping chunk.", a_ChunkX, a_ChunkZ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a copy of the region and limit it to the current chunk:
|
||||||
|
int BlockX = a_ChunkX * 16;
|
||||||
|
int BlockZ = a_ChunkZ * 16;
|
||||||
|
cRegion Local;
|
||||||
|
Local.m_MinX = std::max(0, a_Region.m_MinX - BlockX);
|
||||||
|
Local.m_MaxX = std::min(15, a_Region.m_MaxX - BlockX);
|
||||||
|
Local.m_MinY = a_Region.m_MinY;
|
||||||
|
Local.m_MaxY = a_Region.m_MaxY;
|
||||||
|
Local.m_MinZ = std::max(0, a_Region.m_MinZ - BlockZ);
|
||||||
|
Local.m_MaxZ = std::min(15, a_Region.m_MaxZ - BlockZ);
|
||||||
|
|
||||||
|
if (a_Region.m_ShouldZapBlocks)
|
||||||
|
{
|
||||||
|
int SectionsTag = a_NBT.FindChildByName(LevelTag, "Sections");
|
||||||
|
if (SectionsTag < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Cannot find the Sections tag in the Level tag in chunk [%d, %d]'s NBT. Skipping block-zapping in chunk.", a_ChunkX, a_ChunkZ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ZapRegionBlocksInNBT(Local, a_NBT, SectionsTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_Region.m_ShouldZapEntities)
|
||||||
|
{
|
||||||
|
int EntitiesTag = a_NBT.FindChildByName(LevelTag, "Entities");
|
||||||
|
if (EntitiesTag < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Cannot find the Entities tag in the Level tag in chunk [%d, %d]'s NBT. Skipping entity-zapping in chunk.", a_ChunkX, a_ChunkZ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ZapRegionEntitiesInNBT(Local, a_NBT, EntitiesTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::ZapRegionBlocksInNBT(const cRegion & a_Region, cParsedNBT & a_NBT, int a_SectionsTag)
|
||||||
|
{
|
||||||
|
for (int Child = a_NBT.GetFirstChild(a_SectionsTag); Child >= 0; Child = a_NBT.GetNextSibling(Child))
|
||||||
|
{
|
||||||
|
int y = 0;
|
||||||
|
int SectionY = a_NBT.FindChildByName(Child, "Y");
|
||||||
|
if ((SectionY < 0) || (a_NBT.GetType(SectionY) != TAG_Byte))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
y = a_NBT.GetByte(SectionY);
|
||||||
|
if ((y * 16 > a_Region.m_MaxY) || (y * 16 + 16 < a_Region.m_MinY))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int BlockDataTag = a_NBT.FindChildByName(Child, "Blocks");
|
||||||
|
int BlockMetaTag = a_NBT.FindChildByName(Child, "Data");
|
||||||
|
int BlockAddTag = a_NBT.FindChildByName(Child, "Add");
|
||||||
|
if (BlockDataTag > 0)
|
||||||
|
{
|
||||||
|
ZapRegionInNBTSectionBytes(a_Region, y, (unsigned char *)(a_NBT.GetData(BlockDataTag)));
|
||||||
|
}
|
||||||
|
if (BlockMetaTag > 0)
|
||||||
|
{
|
||||||
|
ZapRegionInNBTSectionNibbles(a_Region, y, (unsigned char *)(a_NBT.GetData(BlockMetaTag)));
|
||||||
|
}
|
||||||
|
if (BlockAddTag > 0)
|
||||||
|
{
|
||||||
|
ZapRegionInNBTSectionNibbles(a_Region, y, (unsigned char *)(a_NBT.GetData(BlockAddTag)));
|
||||||
|
}
|
||||||
|
} // for Child - Level/Sections/[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::ZapRegionInNBTSectionBytes(const cRegion & a_Region, int a_SectionY, unsigned char * a_BlockBytes)
|
||||||
|
{
|
||||||
|
int MinY = std::max(0, a_Region.m_MinY - a_SectionY * 16);
|
||||||
|
int MaxY = std::min(15, a_Region.m_MaxY - a_SectionY * 16);
|
||||||
|
ASSERT(MinY >= 0);
|
||||||
|
ASSERT(MaxY >= 0);
|
||||||
|
for (int y = MinY; y <= MaxY; y++)
|
||||||
|
{
|
||||||
|
for (int z = a_Region.m_MinZ; z <= a_Region.m_MaxZ; z++)
|
||||||
|
{
|
||||||
|
for (int x = a_Region.m_MinX; x <= a_Region.m_MaxX; x++)
|
||||||
|
{
|
||||||
|
a_BlockBytes[x + z * 16 + y * 16 * 16] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::ZapRegionInNBTSectionNibbles(const cRegion & a_Region, int a_SectionY, unsigned char * a_BlockNibbles)
|
||||||
|
{
|
||||||
|
int MinY = std::max(0, a_Region.m_MinY - a_SectionY * 16);
|
||||||
|
int MaxY = std::min(15, a_Region.m_MaxY - a_SectionY * 16);
|
||||||
|
ASSERT(MinY >= 0);
|
||||||
|
ASSERT(MaxY >= 0);
|
||||||
|
for (int y = MinY; y <= MaxY; y++)
|
||||||
|
{
|
||||||
|
for (int z = a_Region.m_MinZ; z < a_Region.m_MaxZ; z++)
|
||||||
|
{
|
||||||
|
for (int x = a_Region.m_MinX; x < a_Region.m_MaxX; x++)
|
||||||
|
{
|
||||||
|
cChunkDef::SetNibble(a_BlockNibbles, x, y, z, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::ZapRegionEntitiesInNBT(const cRegion & a_Region, cParsedNBT & a_NBT, int a_EntitiesTag)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cZapper::SerializeNBTTag(const cParsedNBT & a_NBT, int a_Tag, cFastNBTWriter & a_Writer)
|
||||||
|
{
|
||||||
|
switch (a_NBT.GetType(a_Tag))
|
||||||
|
{
|
||||||
|
case TAG_Byte: a_Writer.AddByte (a_NBT.GetName(a_Tag), a_NBT.GetByte (a_Tag)); break;
|
||||||
|
case TAG_Short: a_Writer.AddShort (a_NBT.GetName(a_Tag), a_NBT.GetShort (a_Tag)); break;
|
||||||
|
case TAG_Int: a_Writer.AddInt (a_NBT.GetName(a_Tag), a_NBT.GetInt (a_Tag)); break;
|
||||||
|
case TAG_Long: a_Writer.AddLong (a_NBT.GetName(a_Tag), a_NBT.GetLong (a_Tag)); break;
|
||||||
|
case TAG_Float: a_Writer.AddFloat (a_NBT.GetName(a_Tag), a_NBT.GetFloat (a_Tag)); break;
|
||||||
|
case TAG_Double: a_Writer.AddDouble (a_NBT.GetName(a_Tag), a_NBT.GetDouble(a_Tag)); break;
|
||||||
|
case TAG_ByteArray: a_Writer.AddByteArray(a_NBT.GetName(a_Tag), a_NBT.GetData (a_Tag), a_NBT.GetDataLength(a_Tag)); break;
|
||||||
|
case TAG_String: a_Writer.AddString (a_NBT.GetName(a_Tag), a_NBT.GetString(a_Tag)); break;
|
||||||
|
case TAG_IntArray:
|
||||||
|
{
|
||||||
|
std::vector<int> Data;
|
||||||
|
int NumInts = a_NBT.GetDataLength(a_Tag) / 4;
|
||||||
|
Data.reserve(NumInts);
|
||||||
|
int * OrigData = (int *)(a_NBT.GetData(a_Tag));
|
||||||
|
for (int i = 0; i < NumInts; i++)
|
||||||
|
{
|
||||||
|
Data.push_back(ntohl(OrigData[i]));
|
||||||
|
}
|
||||||
|
a_Writer.AddIntArray (a_NBT.GetName(a_Tag), &Data.front(), Data.size()); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TAG_List:
|
||||||
|
{
|
||||||
|
a_Writer.BeginList(a_NBT.GetName(a_Tag), a_NBT.GetChildrenType(a_Tag));
|
||||||
|
for (int ch = a_NBT.GetFirstChild(a_Tag); ch >= 0; ch = a_NBT.GetNextSibling(ch))
|
||||||
|
{
|
||||||
|
SerializeNBTTag(a_NBT, ch, a_Writer);
|
||||||
|
} // for ch - children[]
|
||||||
|
a_Writer.EndList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TAG_Compound:
|
||||||
|
{
|
||||||
|
a_Writer.BeginCompound(a_NBT.GetName(a_Tag));
|
||||||
|
for (int ch = a_NBT.GetFirstChild(a_Tag); ch >= 0; ch = a_NBT.GetNextSibling(ch))
|
||||||
|
{
|
||||||
|
SerializeNBTTag(a_NBT, ch, a_Writer);
|
||||||
|
} // for ch - children[]
|
||||||
|
a_Writer.EndCompound();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ASSERT(!"Unknown NBT tag");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
80
Tools/BlockZapper/Zapper.h
Normal file
80
Tools/BlockZapper/Zapper.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
// Zapper.h
|
||||||
|
|
||||||
|
// Declares the cZapper class representing the processor that actually zaps blocks and entities
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Regions.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fwd: ParsedNBT.h
|
||||||
|
class cParsedNBT;
|
||||||
|
class cFastNBTWriter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cZapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cZapper(const AString & a_MCAFolder);
|
||||||
|
|
||||||
|
/// Zaps all the specified regions
|
||||||
|
void ZapRegions(const cRegionVector & a_Regions);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static const int BlocksPerChunkX = 16;
|
||||||
|
static const int BlocksPerChunkZ = 16;
|
||||||
|
static const int ChunksPerMCAX = 32;
|
||||||
|
static const int ChunksPerMCAZ = 32;
|
||||||
|
|
||||||
|
AString m_MCAFolder;
|
||||||
|
|
||||||
|
/// Converts from block coords to MCA coords
|
||||||
|
void BlockToMCA(int a_BlockX, int a_BlockZ, int & a_MCAX, int & a_MCAZ);
|
||||||
|
|
||||||
|
/// Converts from block coords to chunk coords
|
||||||
|
void BlockToChunk(int a_BlockX, int a_BlockZ, int & a_ChunkX, int & a_ChunkZ);
|
||||||
|
|
||||||
|
/// Zaps the specified region in the MCA file with the specified MCA coords
|
||||||
|
void ZapRegionInMCAFile(const cRegion & a_Region, int a_MCAX, int a_MCAZ);
|
||||||
|
|
||||||
|
/** Loads raw compressed chunk data from the specified file
|
||||||
|
* chunk is specified by ChunkHeaderValue, which is the int describing the chunk in file header.
|
||||||
|
*/
|
||||||
|
void LoadChunkData(cFile & a_InFile, int a_ChunkHeaderValue, AString & a_ChunkData, int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
|
/// Zaps the specified region in the raw (compressed) chunk data.
|
||||||
|
void ZapRegionInRawChunkData(const cRegion & a_Region, AString & a_ChunkData, int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
|
/// Zaps the specified region in the specified NBT structure
|
||||||
|
void ZapRegionInNBTChunk(const cRegion & a_Region, cParsedNBT & a_NBT, int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
|
/// Zaps the blocks in the specified region from the specified NBT
|
||||||
|
void ZapRegionBlocksInNBT(const cRegion & a_Region, cParsedNBT & a_NBT, int a_SectionsTag);
|
||||||
|
|
||||||
|
/// Zaps the blocks in the specified bytes (types) from one vertical section (16^3 blocks) of a chunk.
|
||||||
|
void ZapRegionInNBTSectionBytes(const cRegion & a_Region, int a_SectionY, unsigned char * a_BlockBytes);
|
||||||
|
|
||||||
|
/// Zaps the blocks in the specified nibbles (meta, add) from one vertical section (16^3 blocks) of a chunk.
|
||||||
|
void ZapRegionInNBTSectionNibbles(const cRegion & a_Region, int a_SectionY, unsigned char * a_BlockNibbles);
|
||||||
|
|
||||||
|
/// Zaps entities in the specified region from the specified NBT
|
||||||
|
void ZapRegionEntitiesInNBT(const cRegion & a_Region, cParsedNBT & a_NBT, int a_EntitiesTag);
|
||||||
|
|
||||||
|
/// Serializes the NBT subtree into a writer
|
||||||
|
void SerializeNBTTag(const cParsedNBT & a_NBT, int a_Tag, cFastNBTWriter & a_Writer);
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1744,6 +1744,10 @@
|
|||||||
RelativePath="..\source\Generating\ComposableGenerator.h"
|
RelativePath="..\source\Generating\ComposableGenerator.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\source\Generating\DistortedHeightmap.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\source\Generating\FinishGen.cpp"
|
RelativePath="..\source\Generating\FinishGen.cpp"
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user